2011-06-07 18:23:57 +0000 2011-06-07 18:23:57 +0000
152
152

Unix/Linux находит и сортирует по измененной дате

Как я могу сделать простой find, который упорядочит результаты по последним изменениям?

Вот текущий find, который я использую (я делаю экранирование оболочки в PHP, так что это аргументы в пользу переменных):

find '$dir' -name '$str'\* -print | head -10

Как я могу упорядочить поиск по последним изменениям? (Обратите внимание, что я не хочу, чтобы он сортировал ‘после’ поиска, а скорее нахожу результаты, основанные на том, что было изменено в последний раз).

Ответы (17)

168
168
168
2013-02-05 13:31:01 +0000

Используй это:

find . -printf "%T@ %Tc %p\n" | sort -n

printf аргументы из man find :

  • %Tk: Время последней модификации файла в формате, указанном k.

  • @: секунды с 1 января 1970 года, 00:00 GMT, с дробной частью.

  • c: локальная дата и время (Сб. 04 12:02:33 EST 1989).

  • %p: Имя файла.

85
85
85
2011-06-07 18:39:34 +0000

Самым простым методом является использование zsh, благодаря его Glob qualifiers .

print -lr -- $dir/**/$str*(om[1,10])

Если вы нашли GNU, заставьте его напечатать время модификации файла и отсортировать по нему.

find -type f -printf '%T@ %p```
find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^]* //' | head -n 10
```' |
sort -zk 1nr |
sed -z 's/^[^]* //' | tr '```
find . -type f -print |
perl -l -ne '
    $_{$_} = -M; # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_; # sort by increasing age
        print @sorted[0..9];
    }'
```' '\n' | head -n 10

Если у вас есть GNU find, но нет других GNU-утилит, используйте новые строки в качестве разделителей вместо нулей; вы потеряете поддержку имен файлов, содержащих новые строки.

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], reverse=True))[:10]: print f'

Если у вас есть Perl (здесь я предполагаю, что в именах файлов нет новых строк):

0x1&

Если у вас есть Python (также предполагающий отсутствие новых строк в именах файлов):

0x1&

Возможно, есть способ сделать то же самое в PHP, но я этого не знаю.

Если вы хотите работать только с POSIX-инструментами, это довольно сложно; смотрите Как список файлов, отсортированных по дате модификации рекурсивно (нет команды statat!) (пересортировка первых 10 - это простая часть).

41
41
41
2011-06-16 18:11:00 +0000

Вам не нужен ни PHP, ни Python, только ls :

man ls:
-t sort by modification time
-r, reverse order while sorting (--reverse )
-1 list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Если команда * выходит со статусом ошибки (т.е. Слишком длинный список памяток ), то вы можете выполнить итерацию с помощью find. Перефразируя из: Максимальная длина аргументов для нового процесса

  • find . -print0|xargs -0 command (оптимизирует скорость, если find не реализует “-exec +”, но знает “-print0”)
  • find . -print|xargs command (если в аргументах нет пробела)

Если основная часть аргументов состоит из длинного, абсолютного или относительного путей, то попробуйте перенести свои действия в каталог: cd /directory/with/long/path; command * И еще одно быстрое исправление может заключаться в совпадении меньшего количества аргументов: command [a-e]*; command [f-m]*; ...

10
10
10
2012-05-18 07:58:06 +0000

Вам нужно только ls

Вы можете сделать find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;, как указано выше,

или

ls -1rt `find /wherever/your/file/hides -type f`
```.
8
8
8
2014-04-24 08:12:01 +0000

Расширение user195696’s answer :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Для каждого файла сначала выводится числовая метка времени (для сортировки по, затем табуляция \t), затем метка времени, читаемая человеком, затем размер файла (к сожалению, find‘s -printf не может делать в мебибайтах, только в кибибайтах), затем имя файла с относительным путем.

Затем sort -n сортирует его по первому числовому полю.

Затем cut избавляется от того первого числового поля, которое не представляет интереса для пользователя. (Далее печатает второе поле.) По умолчанию разделителем полей является \t или табуляция.

Пример вывода:

Thu 06 Feb 2014 04:49:14 PM EST 64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST 0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST 64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST 0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST 64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST 9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST 9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST 9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST 32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST 0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST 70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST 70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST 70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST 0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST 32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST 32 KiB ./plot_grid.m

Я сознательно сделал файл размером 6 символов поля, потому что если сделать его длиннее, становится трудно визуально различить, насколько велики файлы. Таким образом, файлы размером более 1e6 KiB вырезаются: на 1 char означает 1-9 GB, на 2 char означает 10-99 GB и т.д.


Правка: вот еще одна версия (поскольку find . -printf "%Tc" падает на MinGW/MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Подача вывода типа:

-rw-r--r-- 1 es 23K Jul 10 2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Где:

  • -I{} вызывает появление {}, который заменяется аргументом, и новые строки теперь являются разделителями аргументов (обратите внимание на пробелы в именах файлов выше).

  • ls -G подавляет печать имени группы (пустая трата места).

  • ls -h --si создает читаемые человеком размеры файлов (более корректно с --si).

  • ls -t сортирует по времени, что здесь не имеет значения, но это то, что я обычно использую.

4
4
4
2016-02-24 15:18:34 +0000

Операционная система X вариант ответа @user195696:

  1. С меткой времени:

  2. Без метки времени:

2
2
2
2019-03-12 19:32:27 +0000

У меня есть простое решение, которое работает как для FreeBSD (OS X), так и для Linux:

find . -type f -exec ls -t {} +
2
2
2
2012-07-26 07:42:44 +0000

Я обнаружил, что это делает работу на Mac OS X (и достаточно общую, чтобы работать и на других Unixen):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
1
1
1
2013-12-08 09:14:14 +0000

Использовать:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Эта команда отсортирует файлы по измененной дате.

И отобразить как:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
1
1
1
2014-05-02 11:16:59 +0000

Если ваш выбор find очень прост, вы можете обойтись без него и просто использовать ls:

ls -1 *.cc # -r -t optional
0
0
0
2014-07-04 14:58:50 +0000

Я улучшил ответ Акаша, сделав скрипт, корректно работающий с пробелами в именах файлов:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
0
0
0
2019-09-11 08:23:43 +0000

Существует чистый и надежный способ sort | head по дате:

Использование ls -l для красивой печати

find . ! -type d -printf "%T@ %p```
findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zrn |
        head -zn ${1:--0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dlt${humansize}
}
```" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.] //' |
    xargs -0 ls -lt

В качестве функции bash :

findByDate

Это может быть запущено с одним или двумя аргументами, или даже без:

findByDate -h 12

Пример:

findByDate 42 '-type l'

Перечислит все non каталоги, отсортированные по дате. Замечание:

Даже в большом дереве файловой системы, так как xargs получит уже отсортированный список, порядок файлов останется корректным, даже если ls нужно запустить много раз.

findByDate -0 '( -type l -o -type b -o -type s -o -type c )'

Составит список 12 дополнительных записей non directories, отсортированных по дате, с размером, напечатанным в человеческой читабельной форме

findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zn |
        tail -zn ${1:-+0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dltr${humansize}
}

Составит список 42 дополнительных записей

0x1&

Составит список всех сим-ссылок, блочных устройств, разъемов и устройств символов, отсортированных по дате.

Инвертирование порядка

Замена head на tail и замена переключателя sort и ls:

0x1&

Та же функция, то же использование:

0x1&

0
0
0
2011-06-07 18:33:10 +0000

Я не думаю, что в find есть возможность изменить порядок вывода. -mtime и -mmin позволят вам ограничить результаты только файлами, которые были изменены в течение определенного периода времени, но результат не будет отсортирован - вам придется сделать это самому. В GNU find есть опция -printf, которая, помимо прочего, позволит вам распечатывать время модификации каждого найденного файла (строки форматирования %t или %Tk); это может помочь вам отсортировать результаты find так, как вы хотите.

0
0
0
2018-06-24 23:33:20 +0000

Вы можете использовать stat на BSD и Linux (не на POSIX) таким образом:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Если вы хотите ограничить число:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
0
0
0
2014-05-17 10:55:57 +0000

Если вы хотите заказать все PNG файлы по времени в $PWD:

Этот простой одиночный лайнер дает всю гибкость регеxp на find и на ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
-1
-1
-1
2017-03-28 01:13:40 +0000

Если вы просто хотите получить полный путь к каждому элементу, вы можете записать так.

find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Где -printf “%T@ %p\n ” для указания критериев сортировки (дата), “сортировка -nr ” для сортировки по дате, head -10 для перечисления 10 лучших результатов, cut -d “‘ -f 2 для вырезания метки времени на каждой строке.

-3
-3
-3
2017-03-25 09:09:59 +0000

У меня есть простое решение.

После cd в каталог используйте

find . -iname "*" -ls.

Похожие вопросы

6
10
5
37
10