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"for 循环的 glob。


因此我提出这个改变

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路径名。

相关内容