#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}
. Или вы можете просто удалить эту часть полностью (включая||
). Если ответ сработал для вас, вы можете принять его (если хотите). Спасибо.