根据时间戳获取最新文件

时间:2010-08-16 17:25:43

标签: bash unix shell

我是shell脚本的新手,所以我需要一些帮助,需要如何处理这个问题。

我有一个目录,其中包含以下格式的文件。文件位于名为/ incoming / external / data

的目录中
AA_20100806.dat
AA_20100807.dat
AA_20100808.dat
AA_20100809.dat
AA_20100810.dat
AA_20100811.dat
AA_20100812.dat

如您所见,文件的文件名包含时间戳。即[RANGE] _ [YYYYMMDD] .dat

我需要做的是使用文件名中的时间戳而不是系统时间戳找出哪些文件具有最新日期,并将文件名存储在变量中并将其移动到另一个目录并将其余目录移动到另一个目录。

7 个答案:

答案 0 :(得分:19)

对于那些只想要答案的人来说,这是:

ls | sort -n -t _ -k 2 | tail -1

这是让我来到这里的思考过程。

我将假设[RANGE]部分可以是任何东西。

从我们所知道的开始。

  • 工作目录:/ incoming / external / data
  • 文件格式:[RANGE] _ [YYYYMMDD] .dat

我们需要在目录中找到最新的[YYYYMMDD]文​​件,我们需要存储该文件名。

可用工具(我只列出了解决此问题的相关工具......通过练习识别它们变得更容易):

我想我们不需要sed,因为我们可以使用ls命令的整个输出。使用ls,awk,sort和tail我们可以像这样得到正确的文件(请记住,你必须检查你的操作系统将接受的语法):

NEWESTFILE=`ls | awk -F_ '{print $1 $2}' | sort -n -k 2,2 | tail -1`

然后,只需将下划线放回去,这不应该太难。

编辑:我有一点时间,所以我开始修复命令,至少在Solaris中使用。

这是复杂的第一遍(假设目录中的所有文件格式相同:[RANGE] _ [yyyymmdd] .dat)。我打赌有更好的方法可以做到这一点,但这适用于我自己的测试数据(事实上,我刚刚发现了一种更好的方法;见下文):

ls | awk -F_ '{print $1 " " $2}' | sort -n -k 2 | tail -1 | sed 's/ /_/'

...在写这篇文章时,我发现你可以这样做:

ls | sort -n -t _ -k 2 | tail -1

我会把它分解成几部分。

ls

足够简单......获取目录列表,只是文件名。现在我可以将其输入下一个命令。

awk -F_ '{print $1 " " $2}'

这是AWK命令。它允许您采用输入行并以特定方式对其进行修改。在这里,我正在做的是指定awk应该在有下划线(_)的任何地方断开输入。我使用-F选项执行此操作。这给了我每个文件名的两半。然后我告诉awk输出前半部分($ 1),然后输出一个空格(“”) 接下来是下半场(2美元)。请注意,空间是我最初建议中遗漏的部分。此外,这是不必要的,因为您可以在下面的sort命令中指定分隔符。

现在输出被分成每行的[RANGE] [yyyymmdd] .dat。现在我们可以对此进行排序:

sort -n -k 2

这将获取输入并根据第二个字段对其进行排序。 sort命令默认使用空格作为分隔符。在编写此更新时,我找到了sort文档,它允许您指定分隔符,因此不需要AWK和SED。拿下ls并通过以下方式管道:

sort -n -t _ -k 2

这实现了相同的结果。现在你只需要最后一个文件,所以:

tail -1

如果您使用awk分隔文件(这只是增加额外的复杂性,所以不要这样做羞怯),您可以使用sed替换空格:

sed 's/ /_/'

这里有一些很好的信息,但我相信大多数人都不会像这样读到底部。

答案 1 :(得分:3)

这应该有效:

newest=$(ls | sort -t _ -k 2,2 | tail -n 1)
others=($(ls | sort -t _ -k 2,2 | head -n -1))

mv "$newest" newdir
mv "${others[@]}" otherdir

如果文件名中有空格,它将无效,尽管您可以修改IFS变量来影响它。

答案 2 :(得分:2)

尝试:

$ ls -lr

希望它有所帮助。

答案 3 :(得分:1)

使用:

ls -r -1 AA_*.dat | head -n 1

(假设没有其他文件与AA_*.dat匹配)

答案 4 :(得分:1)

ls -1 AA* |sort -r|tail -1

答案 5 :(得分:1)

由于文件的命名约定,字母顺序与日期顺序相同。我很确定在 bash '*'按字母顺序展开(但在手册页中找不到任何证据), ls 当然可以,所以带有的文件最新的日期,将按字母顺序排在最后一个日期。

因此,在 bash

mv $(ls | tail -1) first-directory
mv * second-directory

应该做的伎俩。

如果您想更具体地选择文件,请将*替换为其他内容 - 例如AA_*.dat

答案 6 :(得分:1)

我对此的解决方案与其他解决方案类似,但有点简单。

ls -tr | tail -1

实际上做的是依靠ls对输出进行排序,然后使用tail来获取最后列出的文件名。

如果您需要的文件名有一个前导点(例如.profile),此解决方案将无效。

如果文件名包含空格,则此解决方案可以正常工作。