for 루프는 여러 디렉터리와 파일을 탐색합니다.

for 루프는 여러 디렉터리와 파일을 탐색합니다.

모든 .bam 파일에 .bai 파일이 포함되어 있는지 확인하고 싶습니다. 따라서 clean_xyz_1.sorted.bam이 존재한다면 clean_xyx_1.sorted.bam.bai도 존재해야 합니다. 각 파일의 중간에는 변수 문자열(xyz)이 있습니다. 여러 폴더를 확인하여 두 파일이 모두 존재하는지 확인하고 싶습니다. 파일이 모두 존재하지 않으면 명령을 실행하고 싶습니다. 그러나 여러 디렉터리에 있는 두 개의 파일을 확인할 수는 없습니다. 내가 시도한 것은 다음과 같습니다.

dirs=(*/)
clean="clean_"
sorted="_1.sorted.bam"

for i in "$dirs"/"$clean"*"$sorted"*; do
  if [[ ! -e "$i".bai ]]; then
  samtools index "$i"
  fi
done

명령이 제대로 실행되고 ".bai" 파일이 생성됩니다. 그러나 첫 번째 디렉터리만 열립니다. 모든 디렉토리를 확장하는 방법이 있습니까?

답변1

dir=(*/)

현재 작업 디렉터리에 디렉터리 배열을 만들어 첫 번째 요소만 인쇄하는 ${dir[@]}대신 사용해야 하는 배열을 반복합니다 .$dir

"$dirs"/"$clean"*"$sorted"*

파일 도 일치합니다 .bai. 이는 원치 않는 동작일 수 있습니다. 그러므로 나는 */"$clean"*"$sorted"glob의 for 루프를 사용하는 것을 권장합니다.


그래서 저는 이런 변화를 제안했습니다.

shopt -s nullglob
clean="clean_"        
sorted="_1.sorted.bam"
                                          
for i in */"$clean"*"$sorted"; do 
  if [[ ! -e "$i".bai ]]; then
    samtools index "$i"
  fi
done

답변2

이를 통해 zsh다음을 수행할 수 있습니다.

dirs=( *(N/) )
prefix=clean_
suffix=_1.sorted.bam

for file ( $^dirs/$prefix*$suffix(N) )
  [[ -e $file.bai ]] || samtools index $file

답변3

dir1, , ... 로 모든 파일을 검색 dir2하고 존재해야 하지만 누락된 파일 이름을 인쇄합니다 .bam..bai

find dir1 dir2 ... -type f -name '*.bam' -print | \
while read name ; do
  bai=${name%.bam}.bai
  [ -f "$bai" ] || printf "missing %s\n" "$bai"
done

이는 개행 문자가 포함된 경로가 없다고 가정하므로 한 줄에 find하나의 전체 .bam경로 이름이 출력됩니다.

관련 정보