如何使用管道获取第 n 个上次修改的子目录中的第 n 个最近文件



我正在做操作系统考试的练习。它需要获取当前目录中第二个最后修改的子目录的第三个最近文件。然后我必须以相反的顺序打印它的行。我不能使用 tac 命令。文本建议使用(awk和sed除外):头,尾,wc。

我已经成功获取了所请求文件的文件名(但我认为方式太复杂了)。现在我必须反向打印它。我想我可以 https://stackoverflow.com/a/744093/11614625 使用这个awk解决方案。

这就是我获取文件名的方式:

ls -t | head | awk '{system("test -d "" $0 "" && echo "" $0 """)}' | awk 'NR==2 {system("ls "" $0 "" | head")}' | awk 'NR==1'

我怎样才能做得更好?如果第三个目录或第二个文件不存在怎么办?

请参阅 https://mywiki.wooledge.org/ParsingLs,awk '{system("test -d "" $0 "" && echo "" $0 """)}'

调用 shell 以调用 awk 以调用系统以调用 shell以调用 test 这显然是一种比仅使用 shell 调用测试更糟糕的方法,如果你要这样做的话。此外,对于大文件,任何将整个文件读入内存的解决方案(就像任何 sed 或朴素的 awk 解决方案一样)对于大文件都会失败,因为它们会超出可用内存。

不幸的是,这就是如何稳健地做你想做的事情:

dir="$(find . -mindepth 1 -maxdepth 1 -type d -printf '%T+t%p' |
sort -rz |
awk -v RS='' 'NR==2{sub(/[^t]+t/,""); print; exit}')" &&
file="$(find "$dir" -mindepth 1 -maxdepth 1 -type f -printf '%T+t%p' |
sort -z |
awk -v RS='' 'NR==3{sub(/[^t]+t/,""); print; exit}')" &&
cat -n "$file" | sort -rn | cut -f2-

如果任何管道中的任何命令失败,则将打印来自失败命令的错误消息,然后不会执行其他命令,并且总体退出状态将是该失败命令的失败状态。

我使用cat | sort | cut而不是awksed来反向打印文件,因为awk(除非您在其中写入需求分页)或sed必须立即将整个文件读入内存,因此对于非常大的文件会失败,而排序旨在通过根据需要对 tmp 文件使用分页来处理大文件,并且仅将文件的一部分保留在内存中时间,因此仅受设备上有多少可用磁盘空间的限制。

以上要求 GNU 工具来提供/处理 NUL 行尾 - 如果您没有这些,请在find命令中将更改为n,从排序选项中删除z,并从 awk 命令中删除-v RS='',并注意结果仅在您的目录或文件名不包含换行符时才有效。

最新更新