如何使Bash脚本merge.sh的source命令仅在merge-all.sh循环首次调用时执行?
解决方案
方案1:用环境变量标记初始化状态
修改merge.sh,让它仅在未完成初始化时执行source /path/init,既避免重复执行,又保留单独运行时的可用性:
#!/bin/sh # # 检查初始化标记,未初始化则执行source if [ -z "$MERGE_INIT_DONE" ]; then source /path/init export MERGE_INIT_DONE=1 fi cd /path_2 INPUT_LIST=/path_3/$1 echo "-----------------------------" echo "Starting script:" $(basename "$0") echo "----------------------------- 0" echo "$INPUT_LIST" #hadd -f "${INPUT_LIST%.txt}.root" @"$INPUT_LIST"
在merge-all.sh中,你可以提前执行一次初始化(可选操作,不提前的话merge.sh第一次调用时也会自动执行),确保循环启动前完成初始化:
#!/bin/sh # 提前初始化,避免第一次调用merge.sh时重复执行 source /path/init export MERGE_INIT_DONE=1 # 你的循环逻辑示例 for input_file in /path_3/*.txt; do ./merge.sh "$(basename "$input_file")" done
这种方式下,无论是单独运行merge.sh,还是通过merge-all.sh循环调用,source /path/init只会执行一次。
方案2:通过参数显式控制初始化
给merge.sh添加可选参数--skip-init,当merge-all.sh调用时传入该参数,跳过初始化步骤:
修改后的merge.sh:
#!/bin/sh # # 检查是否传入跳过初始化的参数 if [ "$1" != "--skip-init" ]; then source /path/init else # 移除跳过参数,确保后续逻辑能正常处理输入列表 shift fi cd /path_2 INPUT_LIST=/path_3/$1 echo "-----------------------------" echo "Starting script:" $(basename "$0") echo "----------------------------- 0" echo "$INPUT_LIST" #hadd -f "${INPUT_LIST%.txt}.root" @"$INPUT_LIST"
merge-all.sh中先完成初始化,再循环调用merge.sh并传入参数:
#!/bin/sh source /path/init # 循环调用示例 for input_file in /path_3/*.txt; do ./merge.sh --skip-init "$(basename "$input_file")" done
这个方案逻辑更显式,适合需要精确控制初始化时机的场景。
关键说明
- 方案1利用环境变量在父进程(merge-all.sh)和子进程(merge.sh)间传递状态,子进程能读取到父进程导出的变量,从而跳过重复初始化。
- 两个方案都保证了
merge.sh的独立性:单独运行时会自动执行初始化,配合merge-all.sh时则避免资源浪费。
内容的提问来源于stack exchange,提问作者MrBoson
相关产品推荐
相关产品推荐

