如何转到每个目录并对特定文件执行命令?

如何转到每个目录并对特定文件执行命令?

如何编写一个 bash 脚本来遍历parent_directory 中的每个目录并对特定文件执行命令。

目录结构如下:

Parent_dir/
  dir1/
   acc.bam
  dir2/
   acc.bam
  dir3/
   acc.bam
... around 30 directories

这是我想使用的命令:

java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output

答案1

通常的习语是

for d in Parent_dir/*/
do
     (cd "$d" && $command)
done

for循环对 .txt 文件中的每个目录直接执行一次Parent_dir。对于每个目录,都会生成一个子 shell;在子 shell 中,我们尝试更改到该目录(这可能会失败,例如,如果我们没有足够的权限),如果成功,则执行命令。无论我们是否成功,cd对父 shell 都没有影响,所以我们不需要担心在那里的位置错误。


如果你想让它更健壮,你可以

    (cd "$d" && test -r acc.bam &&  $command)

确保acc.bam该目录中存在并且可读。您还可以添加 atest -w .以避免尝试在不可写的目录中运行该命令。


PS 以上都不是 Bash 特有的;您可以相当方便地使用 /bin/sh 。

答案2

使用 . 循环遍历父目录中的文件for FILE in *; do ...; done。如果该文件是一个目录,则cd进入该目录,执行您的命令,然后cd ...

cd $parent_directory
for FILE in *; do
    if [ -d "$FILE" ]; then
        cd "$FILE"
        java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output
        cd ..
    fi
done

您还可以在命令中使用文件名来避免更改目录,例如I="$FILE/acc.bam".

答案3

您需要做的就是进入parent_directory 中的每个目录并运行java 命令。要返回到parent_directory,请使用:

cd ..

要获取parent_directory中的目录列表,您可以使用:

find -mindepth 1 -maxdepth 2 -type d

它将仅列出目录并且仅列出一个嵌套级别。

循环看起来像这样:

cmd="java8 -jar /picard.jar CollectRnaSeqMetrics REF_FLAT=/refFlathuman.refflat STRAND_SPECIFICITY=NONE I=acc.bam O=output"
for path in `find -mindepth 1 -maxdepth 2 -type d` 
do
    cd "$path"
    $cmd
    cd ..
done

Java 命令被放置在单独的变量中以使脚本更具可读性。

答案4

通过支持(BSD、GNU,至少)find的实现:-execdirsfind

find ParentDir -name acc.bam -execdir \
  java8 -jar /picard.jar CollectRnaSeqMetrics \
  REF_FLAT=/refFlathuman.refflat \
  STRAND_SPECIFICITY=NONE I=acc.bam O=output \;

相关内容