如何编写一个 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
的实现:-execdir
sfind
find ParentDir -name acc.bam -execdir \
java8 -jar /picard.jar CollectRnaSeqMetrics \
REF_FLAT=/refFlathuman.refflat \
STRAND_SPECIFICITY=NONE I=acc.bam O=output \;