如何将Shell命令输出按行解析为两个变量,处理含空格文件名
解决带空格文件名的
du输出解析问题 这个坑我之前踩过好几次!用空格分割数组的方式处理命令输出,碰到文件名里有空格、制表符甚至特殊字符的时候直接就崩了——毕竟shell默认就是按空白字符拆分的。咱们换个按行解析的思路,用read命令就能完美解决。
核心方案:用while read逐行提取
直接把du的输出通过管道传给while read,让它帮咱们拆分大小和文件名:
du -sc * | sort -hr | while read -r size filename; do # 这里就可以直接使用$size(大小)和$filename(完整文件名,含空格)了 echo "文件/目录:$filename,大小:$size" # 这里可以加你生成条形图的逻辑,比如根据size计算星号数量之类的 done
为什么这个方法管用?
read -r size filename会把每行的第一个空白分隔的部分赋值给size,剩下的所有内容(不管有多少空格)都会完整赋值给filename,完美保留带空格的文件名。-r参数很重要:它会让read不把反斜杠当成转义字符,确保文件名里的特殊字符(比如反斜杠)也能被正确读取。
如果需要把数据存到数组里(后续批量处理)
上面的while循环默认在子shell里运行,循环里的变量没法在外部使用。如果要把大小和文件名存到数组里供后续处理,可以用进程替换让循环在当前shell执行:
# 初始化两个数组分别存大小和文件名 declare -a file_sizes=() declare -a file_names=() # 用进程替换把du的输出作为循环输入 while read -r size filename; do file_sizes+=("$size") file_names+=("$filename") done < <(du -sc * | sort -hr) # 现在可以在循环外使用数组了 for idx in "${!file_sizes[@]}"; do echo "第$((idx+1))项:${file_names[$idx]},大小:${file_sizes[$idx]}" done
额外小提示
- 如果需要包含隐藏文件(以
.开头的文件/目录),可以先执行shopt -s dotglob让*匹配隐藏文件,再运行du命令。 - 如果你用的是BSD版本的
du(比如macOS上的),du的参数可能略有不同,不过核心的read解析逻辑是通用的。
内容的提问来源于stack exchange,提问作者ltpour
相关产品推荐
相关产品推荐

