CLI可正常执行的find命令在bash脚本中处理带空格路径报错问题
问题根因
你遇到的报错本质是两个Bash常见的变量解析问题共同导致的:
- 变量未加双引号触发Shell分词
- 文件内的转义符和
read命令的处理逻辑冲突
1. 变量未加双引号的分词问题
Bash中直接使用未被双引号包裹的变量时,Shell会默认按照IFS(内部字段分隔符,默认包含空格、制表符、换行符)对变量值做拆分,把拆分后的多个片段作为独立参数传给调用的命令。
你脚本里写的find -f $line执行时,带空格的路径会被拆成/foo/bar/pictures\、of\、coffee\、cups/coffee-cup-42.jpg四个独立参数,find会把这四个片段当成四个不同的路径去查找,自然会报找不到文件的错误。
你在终端直接输入命令时,路径里的反斜杠会被Shell直接解析为「将后一个空格转为普通字符」的标记,不会触发分词,所以命令可以正常执行。
2. 文件内转义符的处理问题
你在list.txt里给路径的空格加了反斜杠转义,但read -r命令的-r参数会保留反斜杠本身,不会像终端输入时自动把反斜杠当成转义标记吃掉,最终读取到的$line值里会包含多余的反斜杠,也会导致路径匹配失败。
修正方案
按照下面的步骤修改即可完全适配带空格的路径场景:
- 修改list.txt的存储格式:移除所有路径里的转义反斜杠,直接存储原始路径内容:
/foo/bar/mydirectory/myfile.jpg /foo/bar/mydirectory/deletedfile.jpg /foo/bar/pictures of coffee cups/coffee-cup-42.jpg
- 所有使用
$line的位置统一加双引号:避免Shell分词。 - 优化错误重定向和文件大小获取逻辑:不要用
exec 2>/dev/null全局重定向错误,只针对find命令单独重定向即可;获取文件大小不用嵌套find+ls+awk,直接用stat命令更高效可靠。
修正后的完整脚本
#!/bin/bash LISTOFFILES="/foo/bar/list.txt" REPORT="./result_report.log" FILESTESTED=0 SPACETOTAL=0 FILES_FOUND_COUNT=0 while IFS= read -r line || [[ -n "$line" ]]; do ((FILESTESTED++)) # 仅对当前find命令重定向错误,避免影响全局 FOUND="$(find -f "$line" 2>/dev/null)" if [[ "$FOUND" == "$line" ]]; then echo "FOUND: $line" >> "$REPORT" # 直接用stat获取文件大小,单位为字节 FILESIZE="$(stat -c "%s" "$line")" echo "SIZE is: $FILESIZE" >> "$REPORT" echo "-----------------------------------" >> "$REPORT" ((SPACETOTAL += FILESIZE)) ((FILES_FOUND_COUNT++)) fi done < "$LISTOFFILES"
补充说明:循环末尾加
|| [[ -n "$line" ]]是为了兼容list.txt最后一行没有换行符的场景,避免漏掉最后一行路径。
内容的提问来源于stack exchange,提问作者Tom S
相关产品推荐
相关产品推荐

