bash 根据时间戳获取最新文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3495609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get the newest file based on timestamp
提问by ziggy
I am new to shell scripting so i need some help need how to go about with this problem.
我是 shell 脚本的新手,所以我需要一些帮助来解决这个问题。
I have a directory which contains files in the following format. The files are in a diretory called /incoming/external/data
我有一个目录,其中包含以下格式的文件。这些文件位于名为 /incoming/external/data 的目录中
AA_20100806.dat
AA_20100807.dat
AA_20100808.dat
AA_20100809.dat
AA_20100810.dat
AA_20100811.dat
AA_20100812.dat
As you can see the filename of the file includes a timestamp. i.e. [RANGE]_[YYYYMMDD].dat
如您所见,文件的文件名包含时间戳。即 [RANGE]_[YYYYMMDD].dat
What i need to do is find out which of these files has the newest date using the timestamp on the filename not the system timestamp and store the filename in a variable and move it to another directory and move the rest to a different directory.
我需要做的是使用文件名上的时间戳而不是系统时间戳找出这些文件中哪些文件具有最新日期,并将文件名存储在一个变量中并将其移动到另一个目录并将其余文件移动到另一个目录。
回答by Marc Reside
For those who just want an answer, here it is:
对于那些只想要答案的人,这里是:
ls | sort -n -t _ -k 2 | tail -1
Here's the thought process that led me here.
这是引导我来到这里的思考过程。
I'm going to assume the [RANGE] portion could be anything.
我将假设 [RANGE] 部分可以是任何东西。
Start with what we know.
从我们所知道的开始。
- Working Directory: /incoming/external/data
- Format of the Files: [RANGE]_[YYYYMMDD].dat
- 工作目录:/incoming/external/data
- 文件格式:[RANGE]_[YYYYMMDD].dat
We need to find the most recent [YYYYMMDD] file in the directory, and we need to store that filename.
我们需要在目录中找到最新的 [YYYYMMDD] 文件,我们需要存储该文件名。
Available tools (I'm only listing the relevant tools for this problem ... identifying them becomes easier with practice):
可用的工具(我只列出了解决这个问题的相关工具......通过实践识别它们变得更容易):
I guess we don't need sed, since we can work with the entire output of ls command. Using ls, awk, sort, and tail we can get the correct file like so (bear in mind that you'll have to check the syntax against what your OS will accept):
我想我们不需要 sed,因为我们可以使用 ls 命令的整个输出。使用 ls、awk、sort 和 tail,我们可以获得正确的文件,如下所示(请记住,您必须根据操作系统接受的内容检查语法):
NEWESTFILE=`ls | awk -F_ '{print }' | sort -n -k 2,2 | tail -1`
Then it's just a matter of putting the underscore back in, which shouldn't be too hard.
然后只需将下划线放回原处,这应该不会太难。
EDIT: I had a little time, so I got around to fixing the command, at least for use in Solaris.
编辑:我有一点时间,所以我开始修复命令,至少在 Solaris 中使用。
Here's the convoluted first pass (this assumes that ALL files in the directory are in the same format: [RANGE]_[yyyymmdd].dat). I'm betting there are better ways to do this, but this works with my own test data (in fact, I found a better way just now; see below):
这是令人费解的第一遍(假设目录中的所有文件都采用相同的格式:[RANGE]_[yyyymmdd].dat)。我打赌有更好的方法可以做到这一点,但这适用于我自己的测试数据(事实上,我刚刚找到了更好的方法;见下文):
ls | awk -F_ '{print " " }' | sort -n -k 2 | tail -1 | sed 's/ /_/'
... while writing this out, I discovered that you can just do this:
...在写这篇文章时,我发现你可以这样做:
ls | sort -n -t _ -k 2 | tail -1
I'll break it down into parts.
我会把它分成几部分。
ls
Simple enough ... gets the directory listing, just filenames. Now I can pipe that into the next command.
足够简单...获取目录列表,只是文件名。现在我可以将其通过管道传输到下一个命令中。
awk -F_ '{print " " }'
This is the AWK command. it allows you to take an input line and modify it in a specific way. Here, all I'm doing is specifying that awk should break the input wherever there is an underscord (_). I do this with the -F option. This gives me two halves of each filename. I then tell awk to output the first half ($1), followed by a space (" ") , followed by the second half ($2). Note that the space was the part that was missing from my initial suggestion. Also, this is unnecessary, since you can specify a separator in the sort command below.
这是 AWK 命令。它允许您获取输入行并以特定方式对其进行修改。在这里,我所做的只是指定 awk 应该在有下划线 (_) 的地方中断输入。我使用 -F 选项执行此操作。这给了我每个文件名的两半。然后我告诉 awk 输出前半部分 ($1),后跟一个空格 (" ") ,后跟后半部分 ($2)。请注意,空间是我最初建议中缺少的部分。此外,这是不必要的,因为您可以在下面的排序命令中指定分隔符。
Now the output is split into [RANGE] [yyyymmdd].dat on each line. Now we can sort this:
现在,输出在每行上拆分为 [RANGE] [yyyymmdd].dat。现在我们可以这样排序:
sort -n -k 2
This takes the input and sorts it based on the 2nd field. The sort command uses whitespace as a separator by default. While writing this update, I found the documentation for sort, which allows you to specify the separator, so AWK and SED are unnecessary. Take the ls and pipe it through the following sort:
这需要输入并根据第二个字段对其进行排序。sort 命令默认使用空格作为分隔符。在编写此更新时,我找到了 sort 的文档,它允许您指定分隔符,因此 AWK 和 SED 是不必要的。获取 ls 并将其通过以下排序进行管道传输:
sort -n -t _ -k 2
This achieves the same result. Now you only want the last file, so:
这实现了相同的结果。现在你只想要最后一个文件,所以:
tail -1
If you used awk to separate the file (which is just adding extra complexity, so don't do it sheepish), you can replace the space with an underscore again with sed:
如果您使用 awk 来分隔文件(这只是增加了额外的复杂性,所以不要害羞),您可以使用 sed 再次用下划线替换空格:
sed 's/ /_/'
Some good info here, but I'm sure most people aren't going to read down to the bottom like this.
这里有一些很好的信息,但我相信大多数人不会像这样深入阅读。
回答by Paused until further notice.
This should work:
这应该有效:
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
It won't work if there are spaces in the filenames although you could modify the IFSvariable to affect that.
如果文件名中有空格,它将不起作用,尽管您可以修改IFS变量来影响它。
回答by Pablo Santa Cruz
Try:
尝试:
$ ls -lr
Hope it helps.
希望能帮助到你。
回答by igor
Use:
用:
ls -r -1 AA_*.dat | head -n 1
(assuming there are no other files matching AA_*.dat)
(假设没有其他文件匹配AA_*.dat)
回答by ghostdog74
ls -1 AA* |sort -r|tail -1
回答by Beano
Due to the naming convention of the files, alphabetical order is the same as date order. I'm pretty sure that in bash'*' expands out alphabetically (but can not find any evidence in the manual page), lscertainly does, so the file with the newest date, would be the last one alphabetically.
由于文件的命名约定,字母顺序与日期顺序相同。我很确定在bash 中'*' 按字母顺序展开(但在手册页中找不到任何证据),ls肯定会,因此具有最新日期的文件将是按字母顺序排列的最后一个。
Therefore, in bash
因此,在bash
mv $(ls | tail -1) first-directory
mv * second-directory
Should do the trick.
应该做的伎俩。
If you want to be more specific about the choice of file, then replace *with something else - for example AA_*.dat
如果您想更具体地选择文件,请替换*为其他内容 - 例如AA_*.dat
回答by Chris Woollard
My solution to this is similar to others, but a little simpler.
我对此的解决方案与其他解决方案类似,但更简单一些。
ls -tr | tail -1
What is actually does is to rely on ls to sort the output, then uses tail to get the last listed file name.
实际上是依靠 ls 对输出进行排序,然后使用 tail 获取最后列出的文件名。
This solution will not work if the filename you require has a leading dot (e.g. .profile).
如果您需要的文件名有前导点(例如 .profile),则此解决方案将不起作用。
This solution does work if the file name contains a space.
如果文件名包含空格,此解决方案确实有效。

