Bash脚本:如何向函数传入多文件夹下的多文件并执行
嘿,我来帮你搞定这个Bash脚本的问题~你的需求是遍历所有Scenario文件夹,把里面的txt文件批量传给自定义函数,最后在对应文件夹生成output.txt对吧?之前用find的写法有几个语法和逻辑问题,下面给你两种可靠的实现方案,还会帮你分析之前的问题出在哪。
先说说你之前写法的问题
你用的$(find . iname $folder/*.txt)有几个明显的错误:
iname前面缺了连字符,find的选项必须是-iname$folder/*.txt会被Shell先尝试展开,如果文件夹里没有匹配的txt文件,这个字符串会原封不动传给find,导致find找不到文件- 就算能找到文件,直接用
$(find ...)获取结果的话,文件名里的空格会被当成参数分隔符,导致文件名被拆成多个错误的参数
解决方案
下面两种方案分别适合不同场景,你可以根据自己的需求选:
方案一:简单场景(文件名无特殊字符/不需要递归)
如果你的Scenario文件夹都在当前目录下,且txt文件名里没有空格、引号这类特殊字符,这个写法简洁又好用:
# 定义你的自定义处理函数,这里用合并文件内容做示例,你替换成自己的逻辑 my_custom_function() { # "$@" 代表传入的所有txt文件参数,能正确保留每个文件名 cat "$@" } build() { # 遍历当前目录下所有名为Scenario的文件夹 for folder in */Scenario/; do # 跳过不存在的路径(防止glob匹配不到时出错) [ -d "$folder" ] || continue # 收集当前文件夹下的所有txt文件,存到数组里 txt_files=("$folder"*.txt) # 检查是否有有效txt文件 if [ ${#txt_files[@]} -eq 0 ] || [ ! -f "${txt_files[0]}" ]; then echo "⚠️ 警告:$folder 下没有找到txt文件" continue fi # 调用自定义函数,把结果写入对应文件夹的output.txt my_custom_function "${txt_files[@]}" > "$folder/output.txt" echo "✅ 已处理 $folder,生成output.txt" done }
如果需要匹配嵌套目录里的Scenario(比如foo/bar/Scenario),只需要在build函数开头加一行shopt -s globstar,然后把遍历的路径改成**/Scenario/就行。
方案二:健壮场景(支持文件名含空格/递归查找)
如果你的txt文件名可能有空格,或者需要递归查找Scenario文件夹下的所有txt(包括子目录里的),用find配合数组处理会更稳妥:
my_custom_function() { cat "$@" # 替换成你的实际处理逻辑 } build() { # 查找所有名为Scenario的文件夹,用while read处理路径 find . -type d -name "Scenario" | while read -r folder; do # 用find的-print0和readarray的-d ''来安全读取带空格的文件名 readarray -d '' txt_files < <(find "$folder" -maxdepth 1 -type f -name "*.txt" -print0) if [ ${#txt_files[@]} -eq 0 ]; then echo "⚠️ 警告:$folder 下没有找到txt文件" continue fi my_custom_function "${txt_files[@]}" > "$folder/output.txt" echo "✅ 已处理 $folder,生成output.txt" done }
- 去掉
-maxdepth 1就能递归查找Scenario文件夹下所有子目录里的txt文件 -print0和readarray -d ''的组合能完美处理带空格、换行符的文件名,避免参数拆分错误
关键注意点
- 自定义函数里一定要用
"$@"来接收参数,不能直接用$@(不带引号),否则带空格的文件名会被拆成多个参数 - 用数组存储文件列表是处理特殊文件名的核心,能保证每个文件名作为独立的参数被传递
内容的提问来源于stack exchange,提问作者LearningSlowly
相关产品推荐
相关产品推荐

