未知命令输出行数时,如何获取除最后一行外的所有内容?
如何在不预知输出行数的情况下获取除最后一行外的所有内容?
当然可以!不用提前数行数,有好几种简洁的命令行工具组合能帮你搞定这个需求,我来给你拆解几个实用的方案,顺便修正原命令里的小问题:
最简洁的方案:用sed直接删除最后一行
sed '$d' 是专门干这个的——$在sed里代表最后一行,d是删除操作,所以这个命令会直接砍掉输入的最后一行,剩下的就是你要的内容。
不过要注意:你原命令里直接用rm -rf $line会出错,因为ls -l的每一行包含权限、所有者、日期这些信息,不是纯文件名。得先提取每行的最后一列(也就是文件名/目录名),用awk '{print $NF}'就能搞定。另外,ls -l的第一行是total统计行,也不能用来删除,所以还要把这行去掉。
放到你的场景里,完整命令是:
ls -l | sed "s/$USER/me/g" | sed '1d;$d' | while IFS= read -r line; do filename=$(echo "$line" | awk '{print $NF}') rm -rf "$filename" done
这里IFS= read -r line是为了处理文件名里包含空格的情况,避免被错误分割。
用awk实现缓存式输出
awk也能轻松搞定,思路是缓存上一行的内容,处理到下一行时再打印上一行,这样最后一行就不会被输出:
ls -l | sed "s/$USER/me/g" | awk 'NR>1{print last} {last=$0; next} END{}' | while IFS= read -r line; do filename=$(echo "$line" | awk '{print $NF}') rm -rf "$filename" done
NR是awk内置的行号变量,当行号大于1时,打印之前缓存的last(也就是上一行内容),然后把当前行存到last里,循环到最后,最后一行就不会被打印了。
反向处理:tac+sed组合
tac命令会把输入内容倒序输出,我们先倒序,删除第一行(也就是原来的最后一行),再倒回来就得到了目标内容:
ls -l | sed "s/$USER/me/g" | tac | sed '1d' | tac | sed '1d' | while IFS= read -r line; do filename=$(echo "$line" | awk '{print $NF}') rm -rf "$filename" done
这里最后加的sed '1d'还是用来去掉开头的total行。
额外提醒:更可靠的替代方案
如果你的目标只是保留最后一个文件/目录,其实还有更直接的方式——用数组存储所有文件,排除最后一个再删除,完全不用处理ls的输出,更适合文件名含特殊字符的场景:
files=(*) # 保留最后一个,删除前面的所有项 for ((i=0; i<${#files[@]}-1; i++)); do rm -rf "${files[$i]}" done
内容的提问来源于stack exchange,提问作者Wizard
相关产品推荐
相关产品推荐

