Bash脚本用cut处理CSV路径时首行被删除故障排查
问题根因
首行丢失是while read和cut的标准输入抢占导致的:
- 你写的
while read in每次从源CSV读取一行存入变量in,但循环内的cut命令没有接收到这行内容,默认直接从当前shell的标准输入(也就是while循环正在读取的同一个源CSV文件)拉取数据。 - 第一次进入循环时,
read已经读取了文件第一行,此时cut启动后直接抢占输入流,从当前文件指针位置(也就是第二行开头)一口气把剩余所有内容读取处理完才退出。等cut执行结束,文件指针已经到末尾,while循环直接终止,第一行内容从来没被传给cut处理,自然就消失了。 - 你之前尝试加空行的方案没用,是因为空行只是占了被
read读走的第一行位置,真正的第一行路径还是会变成cut启动后读取的第一块内容,首行丢失的问题没有本质改变。 - 额外提一句:你当前的
find命令存在逻辑隐患,find的-o优先级低于隐式的-print动作,如果不加括号包裹所有匹配条件,重定向只会捕获最后一个-name "*.hdr"的匹配结果,你现在源CSV内容完整属于环境下的巧合,后续很容易出现漏统计文件的问题。
修复方案
根本不需要写while read逐行循环,cut本身就支持直接读取整个文件批量处理,既可以彻底规避输入流抢占的bug,执行效率也比逐行启动进程高得多。
- 直接删除整个错误的
while read代码块,替换为单行直接处理的cut命令:
cut -d'/' -f6- /users/krzysztofpaszta/CSVtemporary2/ASSETS-LIST-"$dir".csv >> /users/krzysztofpaszta/CSVtoGD2/"$dir".csv
- 给find命令的所有匹配条件加括号分组,修复匹配逻辑漏洞,修改后的find命令写法:
find /users/krzysztofpaszta/temporaryprojects/"$dir" \( \ -name "*.fnt" -o -name "*.png" -o -name "*.ttf" -o -name "*.asset" -o \ -name "*.jpeg" -o -name "*.tga" -o -name "*.tif" -o -name "*.bmp" -o \ -name "*.jpg" -o -name "*.fbx" -o -name "*.prefab" -o -name "*.flare" -o \ -name "*.ogg" -o -name "*.wav" -o -name "*.anim" -o -name "*.mp3" -o \ -name "*.tiff" -o -name "*.otf" -o -name "*.hdr" \ \) >> /users/krzysztofpaszta/CSVtemporary2/ASSETS-LIST-"$dir".csv
补充:如果确实需要用while逐行处理的场景,必须显式把读取到的行内容传给cut,写法为echo "$in" | cut -d'/' -f6- >> 目标文件,但这种写法每处理一行就要启动一次cut进程,文件量大时性能很差,非必要不使用。
内容的提问来源于stack exchange,提问作者Kamilminiprogramer
相关产品推荐
相关产品推荐

