用于查找文件列表中最新的的脚本

用于查找文件列表中最新的的脚本

我需要编写一个名为的脚本newer.sh,给定文件列表,返回最新的文件。也就是说,输入:

newer.sh /some/file other-file /and/so/on

将返回列表中最新文件的名称。

到目前为止,这是我能想到的:

#!/bin/bash
echo "Newest file:"
ls -t | head -n 1

它实际上返回根据创建时间创建的最新文件,但仅限于当前目录中的文件。

答案1

使用 GNU 工具:

#! /bin/bash -
export LC_ALL=C
eval "files=($(ls -dt --quoting-style=shell-always -- "${@?}"))"
((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

对于符号链接,这将考虑符号链接本身的最后修改时间。如果您希望它是符号链接的目标,请将该-L选项添加到ls.

如果您想添加限制,即作为参数给出的文件路径不能包含换行符,您可以编写:

#! /bin/sh -
# only works for file paths that don't contain newline characters
[ "$#" -gt 0 ] && ls -td -- "$@" | head -n 1

并消除对 GNU 工具的依赖。

原理是相同的:使用 的ls -t功能按修改时间对文件进行排序并获取该列表中的第一个。但在这里,ls每行输出一个文件列表,这使得无法可靠地解析,除非您可以保证没有一个文件路径包含换行符(否则,您将无法区分名为a<newline>b和两个a文件b,如果a<newline>b是最新的文件,head -n 1则只会显示a实际上给出的错误结果)。

与您的方法相比,这里,我们将脚本接收到的参数列表 ( "$@") 传递给ls(在 a 之后--,以便这些参数被视为ls文件操作数而不是选项)并传递-d选项,以便ls不列出内容这些文件的类型目录。如果脚本收到 0 个参数 ( $#== 0),我们也不会执行此操作,否则ls -td --会列出当前目录,因此您将得到.输出。

除了 GNU 之外ls,您还可以使用 GNUstat以可以使用 GNU 排序的方式检索文件的修改时间sort

#! /bin/sh -
export TZ=UTC0 LC_ALL=C
stat --printf '%y@%n\0' -- "$@" | sort -rz | sed -z 's/^[^@]*@//;q' | tr '\0' '\n'

(使用最新版本的 GNU sedfor -z)。或者使用 GNU awk

#! /bin/sh -
export TZ=UTC0 LC_ALL=C
stat --printf '%y@%n\0' -- "$@" | awk -v RS='\0' '
  NR == 1 || $0 > newest {newest = $0}
  END {if (NR) {sub(/[^@]*@/, "", newest); print newest}}'

相关内容