循环遍历目录一层,并在该目录中以目录名作为参数执行脚本
Posted
技术标签:
【中文标题】循环遍历目录一层,并在该目录中以目录名作为参数执行脚本【英文标题】:Loop over directories one level deep and execute script with directory name as argument in bash in that directory 【发布时间】:2021-12-28 09:13:39 【问题描述】:我有一个批处理脚本,我想用它在特定级别的所有目录上运行。它调用一个脚本(recon1.sh),该脚本将目录名称作为参数并将结果文件夹存储在每个子目录中。 我想要的是,当 pathway_name 从命令行(bash batch_recon1.sh path_X)指定时,它 cd进入每个蛋白质文件夹(蛋白质_A,蛋白质_B,...。蛋白质_Z)并执行recon1.sh并对路径文件夹下的所有蛋白质执行此操作。目前,它在一种蛋白质(蛋白质_A)对于蛋白质_B 和其他蛋白质没有开始之后结束。我怎样才能解决这个问题?我尝试使用更简单的脚本,该脚本仅在子文件夹上循环一层,并将该目录中的 file_names 写入文本文件,效果很好,但由于某种原因,此代码(batch_recon1.sh for recon1.sh)不起作用.有人可以帮忙吗?
文件夹结构:
[软件文件夹]
$HOME/ProjName/software/batch_recon1.sh
$HOME/ProjName/software/recon1.sh
[项目文件夹]
$HOME/ProjName/pathways/Pathway_X/protein_A/
$HOME/ProjName/pathways/Pathway_X/protein_A/protein_A_id
$HOME/ProjName/pathways/Pathway_X/protein_A/protein_A_searchRes
$HOME/ProjName/pathways/Pathway_X/protein_A/protein_A_alignment
$HOME/ProjName/pathways/Pathway_X/protein_B/
$HOME/ProjName/pathways/Pathway_X/protein_B/protein_B_id
$HOME/ProjName/pathways/Pathway_X/protein_B/protein_B_searchRes
$HOME/ProjName/pathways/Pathway_X/protein_B/protein_B_alignment
recon1.sh 将 protein_name 作为参数 (例如 recon1.sh protein_A)
所以 $dirname 应该是(即)“protein_A”而不是蛋白质文件夹的完整路径。
用作(从命令行)bash batch_recon1.sh Pathway_X
batch_recon1.sh的代码:
#!/bin/bash
# -*- coding: utf-8 -*-
set -e
current_path=$(pwd)
pathway_name=$1
path_to_folder=$HOME/ProjName/pathways/$pathway_name
path_to_software_folder=$HOME/ProjName/software
cd $path_to_folder
echo '----running batch_reconcile1.sh on pathway:'$@
for fol in "$path_to_folder"/*/; do
[ -d "$fol" ] || continue ## if not a directory skip
dirname="$(basename "$fol")"
(cd "$fol" && bash $path_to_software_folder/recon1.sh $dirname )
cd ..
done
【问题讨论】:
(cd "$fol" && ...)
在子shell中执行。之后不要cd ..
。注意:更好的双引号所有参数扩展(例如pathway_name="$1"
)。注意:不需要bash $path_to_software_folder/recon1.sh $dirname
。只需"$path_to_software_folder/recon1.sh" "$dirname"
。
感谢@RenaudPacalet!出于某种原因,它一直说“权限被拒绝”。我正在通过 Mac 的 ssh 使用 Ubuntu 18 LTS。
$HOME/ProjName/software/recon1.sh$
是否可执行?如果没有尝试chmod +x $HOME/ProjName/software/recon1.sh
。
【参考方案1】:
脚本可能提前退出,因为 recon1.sh
失败,而您有 set -e
(如果命令失败则退出)。
由于cd ..
不应该存在,它可能会失败。
在所有蛋白质上继续尝试recon1.sh
可能会更好,即使其中一个失败(这取决于你)。
替换
(cd "$fol" && bash $path_to_software_folder/recon1.sh $dirname )
cd ..
与:
cd "$fol" || continue
bash $path_to_software_folder/recon1.sh "$dirname" || echo "recon1.sh failed for $dirname" >&2
工作目录设置正确。如果 recon1.sh
由于任何原因仍然失败,则会打印错误,但脚本不会退出,并尝试下一个蛋白质。
【讨论】:
这确实是我正在寻找的。(次要:由于某种原因,即使它没有失败,它也会打印“recon1.sh failed for protein_name”。)它现在正在工作!谢谢@dan 只有在recon1.sh
返回非零(失败)时才会打印错误。 shell 脚本返回最后执行命令的状态(除非调用了exit <number>
),所以recon1.sh
中的某些命令肯定会失败。它可能只是在完成了您需要它做的事情(或至少做一些事情)之后才这样做。你应该看看recon1.sh
。
感谢您指出@dan。事实上,在日志中有一个“没有这样的文件或目录”错误。 (尽管如此,它似乎已经给出了输出(可能是因为存在从 recon1.sh 调用的旧版本的文件)。
@007 不用担心。也许更好的消息可能是an error occurred in recon1.sh for $dirname
。或者你可以完全删除这部分(包括||
)。如果答案对您有用,您可以接受(如果您愿意)。谢谢。以上是关于循环遍历目录一层,并在该目录中以目录名作为参数执行脚本的主要内容,如果未能解决你的问题,请参考以下文章
如何在linux中使用shell脚本遍历指定目录的文件,将创建时间大于指定时间的文件,复制到指定目录下。