Shell脚本批量合并文件内容(排除首行)仅复制首个文件的问题求助
Shell脚本批量合并文件内容(排除首行)仅复制首个文件的问题求助
嗨,我来帮你分析问题并给出解决方案~
你遇到的核心问题出在shell通配符的展开时机上:当你输入./copy.sh ./folder/*.csv newfile.csv时,你的shell会先把./folder/*.csv展开成所有匹配的CSV文件名列表,比如变成./copy.sh file1.csv file2.csv file3.csv newfile.csv。这时候脚本拿到的参数并不是你以为的$1=./folder/*.csv、$2=newfile.csv,而是$1=file1.csv、$2=file2.csv、$3=file3.csv、$4=newfile.csv。
而你原来的脚本里把FILES=$1,相当于只取了第一个文件名,自然只会处理第一个文件;同时DESTINATION=$2还把第二个文件当成了目标文件,完全偏离了你的预期。
下面给你两种修正后的脚本方案:
方案一:简洁版(适合文件名无空格的场景)
#!/bin/sh # 先检查参数数量是否足够 if [ $# -lt 2 ]; then echo "用法:$0 <要合并的文件列表> <目标文件>" exit 1 fi # 把最后一个参数设为目标文件 DESTINATION=${!#} # 把前面所有参数作为要处理的文件列表 FILES=${@:1:$#-1} for f in $FILES do echo "正在处理文件: $f" awk 'NR>=2' "$f" >> "$DESTINATION" done
方案二:安全数组版(支持文件名带空格/特殊字符)
#!/bin/sh # 参数校验:至少需要传入源文件+目标文件两个参数 if [ $# -lt 2 ]; then echo "用法:$0 <要合并的文件1> <要合并的文件2> ... <目标文件>" exit 1 fi # 提取最后一个参数作为目标文件 DESTINATION="${@: -1}" # 提取除最后一个外的所有参数作为源文件数组 FILES=("${@:1:$#-1}") # 遍历每个源文件处理 for f in "${FILES[@]}" do echo "正在处理文件: $f" awk 'NR>=2' "$f" >> "$DESTINATION" done
使用说明
直接用你原来的调用方式即可:
./copy.sh ./folder/*.csv newfile.csv
这次shell展开通配符后,脚本会自动把前面所有CSV文件当成源文件,最后一个newfile.csv作为目标文件,完美实现“排除首行批量合并”的需求~
另外提醒下:给变量加双引号(比如"$f"、"$DESTINATION")很关键,能避免文件名含空格、特殊字符时出现错误。
备注:内容来源于stack exchange,提问作者k88074




