我正在寻找一种单层外壳,以在目录树中找到最旧的文件。
我正在寻找一种单层外壳,以在目录树中找到最旧的文件。
Answers:
这项工作(已更新,以纳入丹尼尔·安德森的建议):
find -type f -printf '%T+ %p\n' | sort | head -n 1
find
由于我的第一行是空的,因此我得到了空的空间,原因是我的文件名包含换行符。
这有点可移植,并且由于它不依赖于GNU find
扩展-printf
,因此它也可以在BSD / OS X上运行:
find . -type f -print0 | xargs -0 ls -ltr | head -n 1
唯一的缺点是它的大小有所限制ARG_MAX
(对于大多数较新的内核而言,这应该是无关紧要的)。因此,如果getconf ARG_MAX
返回的字符多于我的系统(在我的系统上为262,144),则不会为您提供正确的结果。它也不符合POSIX,因为-print0
和xargs -0
不兼容。
这里概述了一些其他解决方案:如何在目录中找到最新(最新,最早,最旧)文件?–格雷格的维基
xargs: ls: terminated by signal 13
错误。我猜那是SIGPIPE。我不知道为什么在将sort的输出传递到解决方案中时为什么没有出现类似的错误。
head
我认为,一旦读取了一行并因此“破坏”了管道,该命令就会退出。您没有得到该错误,因为sort
似乎没有抱怨它,但ls
在另一种情况下却有抱怨。
xargs
需要多次调用的文件名,则此操作中断ls
。在那种情况下,这些多个调用的排序输出在应该合并时最终被串联在一起。
ls
它,而且要注意最旧的文件,您的解决方案可能会超出命令行长度限制,从而导致ls
多次调用。您将得到错误的答案,但永远不会知道。
保证以下命令命令可与任何种类的奇怪文件名一起使用:
find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat
find -type f -printf "%T@ %T+ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //'
stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')"
使用空字节(\0
)代替换行符(\n
)可确保在文件名之一包含换行符的情况下,仍可以理解find的输出。
该-z
开关使sort和grep都仅将空字节解释为行尾字符。由于没有这样的换向开关,因此我们grep -m 1
改用(只有一次)。
这些命令按执行时间排序(在我的机器上测量)。
第一个命令将是最慢的,因为它必须先将每个文件的mtime转换为人类可读的格式,然后对这些字符串进行排序。用管道输送到猫可避免为输出着色。
第二个命令稍快一些。尽管它仍然执行日期转换,但是对sort -n
从Unix纪元开始经过的秒数进行数字排序()更快。sed删除自Unix时代以来的秒数。
最后一个命令根本不执行任何转换,并且应该比前两个命令快得多。find命令本身不会显示最早文件的mtime,因此需要stat。
尽管可以接受的答案和此处的其他答案都可以胜任,但是如果您有一棵大树,则它们都会对整个文件进行排序。
更好的情况是,我们可以只列出它们并跟踪最旧的,而无需进行排序。
那就是为什么我想出了这个替代解决方案:
ls -lRU $PWD/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($1,0,1)=="/") { pat=substr($1,0,length($0)-1)"/"; }; if( $6 != "") {if ( $6 < oldd ) { oldd=$6; oldf=pat$8; }; print $6, pat$8; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
我希望这可能对您有所帮助,即使这个问题有点老了。
编辑1:此更改允许使用空格分析文件和目录。它的速度足够快,可以将其发布到根目录/
并找到有史以来最旧的文件。
ls -lRU --time-style=long-iso "$PWD"/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($0,0,1)=="/") { pat=substr($0,0,length($0)-1)"/"; $6="" }; if( $6 ~ /^[0-9]+$/) {if ( $6 < oldd ) { oldd=$6; oldf=$8; for(i=9; i<=NF; i++) oldf=oldf $i; oldf=pat oldf; }; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
命令说明:
运行它:
〜$ time ls -lRU“ $ PWD” / * | awk等
最早的日期:19691231
文件:/ home /.../.../ backupold /.../ EXAMPLES / how-to-program.txt
总计比较:111438
真正的0m1.135s
用户0m0.872s
sys 0m0.760s
编辑2:相同的概念,更好的解决方案find
用于查看访问时间(%T
与第一个printf
一起使用,以用于修改时间或%C
用于状态更改)。
find . -wholename "*" -type f -printf "%AY%Am%Ad %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
编辑3:下面的命令波纹管使用修改时间,并且在找到越来越旧的文件时也会打印增量进度,当您有一些不正确的时间戳(例如1970-01-01)时,这很有用:
find . -wholename "*" -type f -printf "%TY%Tm%Td %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; print oldd " " oldf; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
ls
不利于脚本编写,因为其输出并不意味着要用于计算机,输出格式在实现中会有所不同。正如您已经说过find
的,这对于脚本编写很有用,但是在介绍ls
解决方案之前添加该信息也可能会很好。
请使用ls-手册页告诉您如何订购目录。
ls -clt | head -n 2
-n 2是,因此您不会在输出中得到“总计”。如果只需要文件名。
ls -t | head -n 1
并且如果您需要按正常顺序排列列表(获取最新文件)
ls -tr | head -n 1
它比使用find更容易,更快,更可靠-不必担心文件命名格式。它也应该适用于几乎所有系统。
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1
sort -n
。
set $(find /search/dirname -type f -printf '%T+ %h/%f\n' | sort | head -n 1) && echo $2
find ./search/dirname -type f -printf '%T+ %h/%f\n'
在两列中显示日期和文件名。sort | head -n1
保持对应于最旧文件的行。echo $2
显示第二列,即文件名。
find -type f -printf '%T+ %p\n' | sort | head -1