如何递归列出按修改日期排序的文件(无stat命令可用!)


31

如何获取当前目录下所有文件的列表以及它们的修改日期并按该日期排序?

现在我知道如何做到这一点用findstatsort,但对于一些奇怪的原因,stat没有包装盒上的安装,它是不可能的,我能得到它安装。

还有其他选择吗?

PS:gcc未安装


您可以上传已编译的二进制文件并在那里运行吗?
imz-伊万·扎哈拉里舍夫(Ivan Zakharyaschev)2011年

@imz:是的,这是另一种方法。该find -printf动作似乎是最简单的。
alex

Answers:


27

我最短的方法使用zsh:

print -rl -- **/*(.Om)

D如果您还想列出隐藏文件或隐藏目录中的文件,请添加glob限定符)。

如果您有GNU查找,请使其打印文件修改时间并以此排序。我假设文件名中没有换行符。

find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'

如果您有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'

如果您具有对该服务器的SSH访问权限,请在功能更好的计算机上通过sshfs挂载目录:

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

仅使用POSIX工具,要复杂得多,因为没有找到文件修改时间的好方法。检索文件时间的唯一标准方法是ls,并且输出格式取决于语言环境且难以解析。

如果您可以写入文件,并且只关心常规文件,并且文件名中没有换行符,那么这很可怕:在单个目录中创建指向所有文件的硬链接,然后按修改时间对它们进行排序。

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp

最简单的方法可能是find . -print | xargs -n99999 -s999999 ls -ltr。但这有一个问题:(1)xargs可能不允许-m大于512或-s大于5120,并且(b)即使您可以解决这个问题,组合参数列表和环境仍然存在内核施加的最大大小。您的大多数想法(保存Perl和Python的想法)都存在相同的问题,这就是为什么我特别避免构建长命令行的原因。
geekosaur 2011年

特别是,我经常用得到“参数列表太长”的错误zsh在一般情况下递归水珠。
geekosaur 2011年

@geekosaur:只有最后一个可怕的长棍才有较长的命令行问题。在zsh中,您可以使用内置函数做很多事情(例如print -rl **/*,唯一的限制是您有多少可用内存),还有更多zargsfind … | xargs … ls如果xargs最终ls只调用一次,您的提议将正确排序,如果文件名中包含特殊字符,则该提议将不起作用。
吉尔(Gilles)'所以

非常感谢您提供了许多选项的详细答案!:)
Alex

这就是为什么我喜欢zsh。
Profpatsch

14

假设GNU find

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

如果要首先列出最新的文件,请更改1n,11nr,1

如果您没有GNU,find它将变得更加困难,因为ls的时间戳格式变化很大(例如,最近修改的文件具有不同的时间戳风格)。


实际上,您也可以使用以下方式更改日期和时间格式ls --time-style="..."-我不确定这是标准格式还是GNU ls,可能是GNU。
asoundmove 2011年

绝对是GNU。
geekosaur 2011年

@asoundmove:不幸的是,盒子太旧了(RedHat 7.2)并且ls没有该选项。
Alex

7

在Mac上,没有-printf参数可查找,但是您可以改为执行以下操作:

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'



0

忽略隐藏的文件-具有良好且快速的时间戳

很好地处理文件名中的空格-并非您应该使用它们!

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

find通过以下链接可以找到更多丰富的信息。


0

一般而言,按日期查找文件(这对于原始海报不起作用,但我到这里来了,所以我认为其他人也可能如此)。在我的用例中,我想列出文件,以便在删除之前对其进行检查。

使用findutils 4.6.0,我喜欢:

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

上述命令查找文件(-type f)中,在当前工作目录(.),其被修改超过270天前(-mtime +270另外-mtime 0将产生的最后24小时,-mtime -5示出了最后5天)。然后ls按日期列出它们,最新的第一(-exec ls -laFGht --time-style=iso {} \+

这是输出示例:

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

很棒的事情是,一旦列表被检查过,用finddelete命令替换列表部分就很简单了:

find . -type f -mtime +270 -delete
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.