Unix。在特定文件的多个目录中运行脚本,其中路径名具有正则表达式

Unix。在特定文件的多个目录中运行脚本,其中路径名具有正则表达式

我想制作一个 bash 脚本(split.sh),它迭代具有相同后缀的多个目录,然后针对其中的特定文件运行一个函数。我快到了:

#!/bin/bash
path="/mypath/MAP-9-[0-9][0-9][0-9]"

for filename in $path/*bam; do
    [ -e "$filename" ] || continue
    echo $filename
        for chrom in `seq 1 22` X Y
        do
        samtools view -bh $filename $chrom > $path/$chrom.bam
        samtools index > $path/$chrom.bam; 
        done
done

但是,我收到很多此类消息:“split.sh:第 12 行:/mypath/MAP-9-[0-9][0-9][0-9]/6.bam:没有这样的文件或目录”

问题是脚本无法识别路径名的“[0-9][0-9][0-9]”正则表达式部分。我还尝试在方括号中添加转义字符,但没有成功。这一定是一个非常简单的解决方案,但我无法解决它。

这是 tree 命令输出的摘录:

|-- [[
|-- MAP-9-001
|   |-- MAP-9-001.bam
|   `-- MAP-9-001.bam.bai
|-- MAP-9-003
|   |-- MAP-9-003.bam
|   `-- MAP-9-003.bam.bai
|-- MAP-9-005
|   |-- MAP-9-095.bam
|   `-- MAP-9-095.bam.bai
|-- split.sh

答案1

不要与globvs regex(您glob在此处使用的)混淆:

Glob 是 shell 模式,可用于匹配字符串或扩展路径名:

[[ $name = Bob* ]]
rm *.txt

http://mywiki.wooledge.org/glob

脚本的更正版本:

#!/bin/bash

for filename in /path/MAP-9-[0-9][0-9][0-9]/*bam; do
    [[ -e $filename ]] || continue
    echo "$filename"
    for chrom in {1..22} X Y; do
        samtools view -bh "$filename" "$chrom" > "$(dirname "$filename")/$chrom.bam"
        samtools index "$(dirname "$filename")/$chrom.bam"
    done
done

学习如何在shell中正确引用,这非常重要:

“双引号”包含空格/元字符的每个文字以及每一个扩张:"$var""$(command "$var")""${array[@]}""a & b"。用于'single quotes'代码或文字$'s: 'Costs $5 US'ssh host 'echo "$HOSTNAME"'.看
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
何时需要双引号


[[是一个 bash 关键字,类似于(但比)[命令更强大。看http://mywiki.wooledge.org/BashFAQ/031http://mywiki.wooledge.org/BashGuide/TestsAndConditionals。除非你是为 POSIX sh 编写,否则我建议[[

答案2

/mypath/MAP-9-[0-9][0-9][0-9]/*.bam是一个 shell glob,或者文件名扩展表达。它扩展为匹配文件列表 - 您可以使用它来迭代输入文件,但您不能指望它作为“每次迭代”通配符来生成相应的输出文件。我认为您可能想要的是从相应的循环变量生成每个输出文件$filename,如下所示:

#!/bin/bash

shopt -s nullglob

for filename in /mypath/MAP-9-[0-9][0-9][0-9]/*.bam; do
    [ -e "$filename" ] || continue
    echo "$filename"
    for chrom in {1..22} X Y; do
        samtools view -bh "$filename" "$chrom" > "${filename%/*}/${chrom}.bam"
        samtools index > "${filename%/*}/$chrom.bam"
    done
done

贝壳参数扩展 ${filename%/*}扩展为 的值$filename并删除最短的尾随子字符串/*;因此,它为您提供每个输入文件的目录名,然后您可以在其中添加 来$chrom.bam依次形成每个输出文件。

相关内容