查找一行中最旧文件的年龄或返回零

查找一行中最旧文件的年龄或返回零

我想找到某个目录中最旧文件的年龄,或者如果该目录中没有任何文件则返回 0。我还需要一个单行命令来完成它。到目前为止,这是我用于查找目录中最旧文件的年龄(以秒为单位)的命令:

expr $(($(date +%s) - $(stat -c %Y $(ls -lt /path/to/dir/ | tail -1 | awk '{print $NF}'))))

问题是,如果没有文件,则会返回以下错误:

$ expr $(($(date +%s) - $(stat -c %Y $(ls -lt /path/to/dir/ | tail -1 | awk '{print $NF}'))))
stat: cannot stat ‘0’: No such file or directory
-bash: 1554373460 - : syntax error: operand expected (error token is "- ")

因此,在这种情况下,我希望命令仅返回 0 并抑制错误打印输出。

答案1

zshperl

perl -le 'print 0+-M $ARGV[0]' /path/to/dir/*(N-Om[1])

D(如果您还想考虑隐藏文件(但不是.nor ..),请添加glob 限定符)。

请注意,对于符号链接,会考虑其解析到的文件的修改时间。删除-glob 限定符中的 in 以考虑符号链接的修改时间(并使用(lstat$ARGV[0] && -M _)inperl来获取符号链接的寿命)。

这给出了以天为单位的年龄。乘以 86400 即可得到秒数:

perl -le 'print 86400*-M $ARGV[0]' /path/to/dir/*(N-Om[1])
  • (N-Om[1]): 全局限定符:
    • Nnullglob:为该球体打开。因此,如果目录中没有文件,则扩展为空,导致perl's-M返回undef
    • -:导致下一个全局限定符应用于符号链接的目标
    • Om:按修改时间反转(大写)顺序(因此从最旧到最新,例如ls -rt
    • [1]:仅选择第一个匹配的文件
  • -M file:获取文件内容的年龄。
  • 0+86400*强制转换为数字(针对这种undef情况)。

答案2

如果必须是一行:

stat -c %Y ./* 2>/dev/null | awk -v d="$(date +%s)" 'BEGIN {m=d} $0 < m {m = $0} END {print d - m}'
  • stat -c %Y ./* 2>/dev/null打印所有文件的时间戳,忽略错误(因此没有文件将导致没有输出)
  • 使用 awk:

    • -v d="$(date +%s)"将当前时间戳保存在变量中d
    • BEGIN {m=d}初始化md
    • $0 < m {m = $0}跟踪最小值m
    • END {print d - m}打印差异。

相关内容