使用 AWK 从 ls 输出中删除前 8 列

使用 AWK 从 ls 输出中删除前 8 列

我想使用 AWK 从以下输出中删除前 8 列:


ls -l

lrwxrwxrwx 1 user user   23 jul 27 00:04 file1.pdf
-rw-rw-r-- 1 user user  107 may  8 13:59 file 2 with spaces.mp3
lrwxrwxrwx 1 user user   11 jul 24 19:43 file3-with-hyphens.txt
lrwxrwxrwx 1 user user   11 jul 24 19:43 and_another_file4_with_underscores.md
-rw-rw-r-- 1 user user  107 may  8 13:59 file 5 with way more spaces than the rest.mp3

并将结果发送到文本文件。我可以使用可视块选择在 vim 中手动执行此操作,但我更希望使用脚本自动执行此操作。

环顾四周,我发现 页面上,通过更改第 9 个示例的相关部分并根据需要多次将输出通过管道传输到自身,我能够获得所需的结果,但我觉得必须有更好的(更优雅和/或更紧凑)的方法来做到这一点,但无法找到它或想出我自己的。

我的最终代码如下:

awk '{for(i=1;i<=NF;i++)if(i!=x)f=f?f FS $i:$i;print f;f=""}' x=1 ~/file_folder_content.txt | awk '{for(i=1;i<=NF;i++)if(i!=x)f=f?f FS $i:$i;print f;f=""}' x=1 | ... | awk '{for(i=1;i<=NF;i++)if(i!=x)f=f?f FS $i:$i;print f;f=""}' x=1 >> ~/file_folder_content.txt

注 1:我预计该命令的实际输出ls将比这大得多。

注 2:我尝试打印第 9 个字段,但由于某些文件名包含空格,因此只会打印文件名中的第一个单词。

答案1

这应该可以做你想做的事awk

ls -l | awk '$9~/./{for (i=1;i<9;i++){$i=""}; gsub(/^ +/,""); print}'

这是一个略有不同的方法perl

ls -l | perl -lane 'if ($F[7]=~/./) {s/.*$F[7]//; print}'

笔记:我不得不建议你仔细考虑一下你真正想要实现的目标,因为可能还有更好的方法。正如@五彩纸屑,只需打印文件名就可以更直接地完成ls -1

笔记:正如评论中正确指出的那样,此解决方案并不可靠。我想补充一点,没有解析ls可以被认为是安全可靠的。

学习AWK:由于 OP 在评论中解释说这个问题是熟练掌握 AWK 的更广泛探索的一部分,因此我有一些建议。

  • 通过这个优秀的 AWK教程
  • 拿着吧参考指南永远开放
  • 阅读此简短文章关于 AWK 的内置变量
  • 研究 AWK 的无数答案问题在 StackExchange 上
  • 考虑一下替代方案,总结这里

答案2

这看起来像XY问题.ls -1应该会打印您想要的内容。POSIX 要求使用此选项,因此您不太可能ls不支持它。

但是如果你要解析结果,你不应该使用ls一点也不。使用find,最好配合-print0行动。

所以ls不是合适的工具。如果你坚持要解析裸ls输出,那么awk可能也不是合适的工具。理由:

  • 您的列由空格分隔;有时有两个或三个连续的空格,这在每行中有所不同。因此,使用这种简单的分隔符,一行中的文件名可能从第 N 列开始,而另一行中的文件名则从第 (N+1) 列开始。
  • 您可以告诉awk将多个空格视为一个分隔符(awk -F ' +'),但这会使包含许多连续空格的文件名混乱。
  • 因此,您需要一些逻辑来识别文件名在每一行中的起始位置。这是可以做到的(我相信这awk是图灵完备的),但我无法给您任何可行的解决方案。

ls -1甚至不应该被解析的输出也ls -l更糟糕。

相关内容