Зацикливайтесь на каталогах глубиной на один уровень и выполняйте скрипт с именем каталога в качестве аргумента в bash в этом каталоге

#linux #bash #loops #subdirectory

Вопрос:

У меня есть пакетный скрипт, который я хочу использовать для запуска во всех каталогах на определенном уровне. Он вызывает сценарий(recon1.sh), который принимает имя каталога в качестве аргумента и сохраняет папки результатов в каждом подкаталоге. Я хочу, чтобы, когда имя пути указано в командной строке(bash batch_recon1.sh pathway_X), он помещается в каждую папку с белками(protein_A,protein_B, …. protein_Z) и выполняет recon1.sh и сделайте это для всех белков в папке «Путь». В настоящее время он заканчивается после того, как один белок(protein_A) не запускается для protein_B и других. Как я могу это исправить? Я пробовал с более простым сценарием, который зацикливает подпапки только на один уровень глубже и записывает имена файлов в этом каталоге в текстовый файл, который отлично работает, но по какой-то причине этот код(batch_recon1.sh для 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 принимает имя протеина в качестве arg (например, recon1.sh протеин_А)

таким образом, ${dirname} должен быть (т. е.) «protein_A» не полный путь к папке с белками.

используется как (из командной строки) bash batch_recon1.sh путь_х

код для 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}" amp;amp; bash ${path_to_software_folder}/recon1.sh ${dirname} )  cd ..  done  

Комментарии:

1. (cd "${fol}" amp;amp; ...) выполняется в подоболочке. Не cd .. делай этого после этого. Примечание: лучше заключать в двойные кавычки все расширения параметров (например pathway_name="$1" ). Примечание: в этом нет необходимости bash ${path_to_software_folder}/recon1.sh ${dirname} . Просто "${path_to_software_folder}/recon1.sh" "${dirname}" .

2. спасибо @RenaudPacalet ! По какой-то причине он продолжает говорить «В разрешении отказано». Я использую Ubuntu 18 LTS через ssh с Mac.

3. Является ${HOME}/ProjName/software/recon1.sh$ ли он исполняемым? Если не попробуешь chmod x ${HOME}/ProjName/software/recon1.sh .

Ответ №1:

Сценарий, вероятно, завершается рано, потому recon1.sh что происходит сбой, и у вас есть set -e (выход, если команда завершается неудачно).

Вероятно, это сбой, из-за cd .. которого его не должно быть.

Возможно, также будет лучше продолжать попытки recon1.sh со всеми белками, даже если один из них потерпит неудачу (это зависит от вас).

Заменять

 (cd "${fol}" amp;amp; 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}" gt;amp;2  

Рабочий каталог устанавливается правильно. Если recon1.sh по-прежнему по какой-либо причине происходит сбой, выводится сообщение об ошибке, но сценарий не завершается, и предпринимается попытка следующего белка.

Комментарии:

1. Это действительно то, что я искал.(незначительное: по какой-то причине он печатает «recon1.sh не удалось для protein_name», даже если это не удалось.) Теперь это работает! Спасибо @dan

2. Ошибка будет напечатана только в том случае, если recon1.sh возвращает ненулевое значение (сбой). Сценарий оболочки возвращается со статусом последней выполненной команды (если exit lt;numbergt; только она не вызвана), поэтому какая-то команда recon1.sh определенно не выполняется. Возможно, это просто делается после того, как он сделал то, что вам нужно (или, по крайней мере, что-то). Тебе стоит посмотреть recon1.sh .

3. спасибо, что указал на @dan. действительно, в журнале есть ошибка «Нет такого файла или каталога». (Похоже, тем не менее, он выдал правильный вывод (возможно, из-за более старой версии файла, вызванного из recon1.sh существовал )).

4. @007 Не волнуйтесь. Возможно, было бы лучшее сообщение an error occurred in recon1.sh for ${dirname} . Или вы можете просто удалить эту часть полностью (включая || ). Если ответ сработал для вас, вы можете принять его (если хотите). Спасибо.