循环遍历目录一层,并在该目录中以目录名作为参数执行脚本

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脚本遍历指定目录的文件,将创建时间大于指定时间的文件,复制到指定目录下。

如何在 powershell 中更改目录并在该目录中运行文件?

循环遍历目录中的所有文件[重复]

遍历一个目录中的每个文件

如何循环遍历 Perl 目录中的文件? [复制]