操作系统:Linux
文件系统类型:ext3
首选解决方案:Bash(脚本/一行程序)、Ruby或Python
我有几个目录,其中有几个子目录和文件。我需要列出所有这些目录,其构造方式是将每个一级目录列在其中最新创建/修改文件的日期和时间旁边。
为了说明这一点,如果我接触一个文件或修改它的内容向下几级子目录,该时间戳应该显示在第一级目录名旁边。假设我有一个这样的目录:
./alfa/beta/gamma/example.txt
我修改了文件example.txt的内容,我需要在第一级目录alfa旁边以人类可读的形式显示时间,而不是epoch。我已经尝试了一些使用find, xargs, sort和类似的东西,但我不能绕过“alfa”的文件系统时间戳不改变的问题,当我创建/修改文件的几个级别。
这篇文章中的Perl和Python解决方案帮助我解决了Mac OS X上的这个问题:
如何递归地列出按修改日期排序的文件(没有可用的stat命令!)
引自帖子:
Perl:
find . -type f -print |
perl -l -ne '
$_{$_} = -M; # store file age (mtime - now)
END {
$,="\n";
print sort {$_{$b} <=> $_{$a}} keys %_; # print by decreasing age
}'
Python:
find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'
对于简单的ls输出,使用这个。没有参数列表,所以它不能太长:
find . | while read FILE;do ls -d -l "$FILE";done
并以切割的方式将日期,时间和姓名进行了美化:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5
编辑:请注意,当前顶部的答案按修改日期排序。这里的第二个例子也很简单,因为修改日期在每行的第一个-在末尾添加一个排序:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 | sort
此命令适用于Mac OS X:
find "$1" -type f -print0 | xargs -0 gstat——format '%Y:% Y %n' | sort -nr | cut -d: -f2- | head
在Linux上,正如最初的海报所要求的那样,使用stat而不是gstat。
当然,这个答案是user37078的出色解决方案,从评论晋升为完整答案。我混合了CharlesB在Mac OS x上使用gstat的见解,顺便说一下,我是从MacPorts而不是Homebrew获得的coreutils。
下面是我如何将其打包成一个简单的命令~/bin/ls-recent.sh以供重用:
#!/bin/bash
# ls-recent: list files in a directory tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
#
# Where "path" is a path to target directory, "-10" is any argument to pass
# to "head" to limit the number of entries, and "more" is a special argument
# in place of "-10" which calls the pager "more" instead of "head".
if [ "more" = "$2" ]; then
H=more; N=''
else
H=head; N=$2
fi
find "$1" -type f -print0 |xargs -0 gstat --format '%Y :%y %n' \
|sort -nr |cut -d: -f2- |$H $N
我的.profile中有一个我经常使用的别名:
$ alias | grep xlogs
xlogs='sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R'
所以它做了你正在寻找的(除了它不遍历更改日期/时间多层)-寻找最新的文件(*.log和*.log)。本例为储税券文件);此外,它只发现在最后一天修改的文件,然后按时间排序,并通过较少的管道输出:
sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R
注意,我在某些服务器上没有root,但总是有sudo,所以你可能不需要那部分。
下面是一个版本,它可以处理包含空格、换行符和glob字符的文件名:
find . -type f -printf "%T@ %p\0" | sort -zk1nr
找到……-printf打印文件修改时间(Epoch值),后面跟着空格和以\0结尾的文件名。
sort -zk1nr读取以NUL终止的数据,并对其反向排序
由于问题被标记为Linux,我假设GNU核心实用程序是可用的。
你可以用下面的管道:
xargs -0 printf "%s\n"
打印以换行符结束的按修改时间(最近的第一个)排序的修改时间和文件名。
这是我正在使用的(非常有效):
function find_last () { find "${1:-.}" -type f -printf '%TY-%Tm-%Td %TH:%TM %P\n' 2>/dev/null | sort | tail -n "${2:-10}"; }
优点:
不管扫描多少文件,它只生成3个进程
处理包含空格的文件名
适用于大量文件
用法:
find_last [dir [number]]
地点:
目录-要搜索的目录[当前目录]
Number -显示[10]的最新文件数
find_last /etc 4的输出如下所示:
2019-07-09 12:12 cups/printers.conf
2019-07-09 14:20 salt/minion.d/_schedule.conf
2019-07-09 14:31 network/interfaces
2019-07-09 14:41 environment
这实际上应该做OP指定的事情:
Bash中的一行代码:
$ for first_level in `find . -maxdepth 1 -type d`; do find $first_level -printf "%TY-%Tm-%Td %TH:%TM:%TS $first_level\n" | sort -n | tail -n1 ; done
给出如下输出:
2020-09-12 10:50:43.9881728000 .
2020-08-23 14:47:55.3828912000 ./.cache
2018-10-18 10:48:57.5483235000 ./.config
2019-09-20 16:46:38.0803415000 ./.emacs.d
2020-08-23 14:48:19.6171696000 ./.local
2020-08-23 14:24:17.9773605000 ./.nano
中所请求的,即使是在子文件夹中,也会列出这些文件夹中最新文件的人类可读时间戳的每个一级目录
“我需要列出所有这些被构建的目录
使每个一级目录都列在日期旁边的一种方法
以及其中最新创建/修改文件的时间。”
对于那些面对的人
stat: unrecognized option: format
当执行Heppo的答案(查找$1 -type f -exec stat——format '%Y:% Y %n' "{}" \;| sort -nr | cut -d: -f2- | head)
请尝试使用-c键来替换——format,最后调用将是:
find $1 -type f -exec stat -c '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head
这在一些Docker容器中为我工作,在那里stat不能使用——format选项。
@anubhava的回答很好,但不幸的是,它不能在BSD工具上工作——也就是说,它不能与macOS上默认安装的find一起工作,因为BSD find没有-printf操作符。
所以这里有一个变体,适用于macOS + BSD(在我的Catalina Mac上测试),它结合了BSD find与xargs和stat:
$ find . -type f -print0 \
| xargs -0 -n1 -I{} stat -f '%Fm %N' "{}" \
| sort -rn
当我在这里时,这里是我喜欢使用的BSD命令序列,它将时间戳设置为ISO-8601格式
$ find . -type f -print0 \
| xargs -0 -n1 -I{} \
stat -f '%Sm %N' -t '%Y-%m-%d %H:%M:%S' "{}" \
| sort -rn
(注意,与@anubhava的答案不同,我的答案将文件名从find传递给xargs作为单个参数,而不是以\0终止的列表,这将改变在最后输出的内容)
下面是GNU版本(即@anubhava的答案,但是iso-8601格式):
$ gfind . -type f -printf "%T+ %p\0" | sort -zk1nr
相关问:查找缺少选项-printf,现在怎么办?