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

时间:2019-06-07 15:20:27

标签: shell awk sed

我正在做OS考试练习。它需要获取当前目录中倒数第二个子目录的第三个最近文件。然后,我必须以相反的顺序打印其行。我不能使用tac命令。文字建议使用(awk和sed除外):头,尾巴,厕所。

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

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

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

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

1 个答案:

答案 0 :(得分:1)

请参阅https://mywiki.wooledge.org/ParsingLsawk '{system("test -d \"" $0 "\" && echo \"" $0 "\"")}'正在调用shell来调用awk来调用系统来调用shell来调用测试,这显然比刚开始时仅进行shell调用测试要差。要做到这一点。此外,任何将整个文件读入内存的解决方案(如任何sed或天真的awk解决方案都将采用这种解决方案)将无法处理大型文件,因为它们将超过可用内存。

不幸的是,这是稳健地做您想做的事情:

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

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

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

以上要求GNU工具提供/处理NUL行尾-如果没有,请在\0命令中将\n更改为find,删除{{ 1}},然后从awk命令中删除z,请注意,只有在目录或文件名不包含换行符的情况下,结果才有效。