it-swarm.com.ru

Unix/Linux найти и отсортировать по дате изменения

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

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

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

Как я мог иметь этот порядок поиска по самым последним модифицированным? (Обратите внимание, я не хочу, чтобы он сортировал «после» поиска, а скорее находил результаты на основе того, что было недавно изменено.)

119
Richard Easton

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

find . -printf "%[email protected] %Tc %p\n" | sort -n

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

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

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

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

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

127
user195696

Самый простой способ - использовать zsh благодаря его glob qualifiers .

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

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

find -type f -printf '%[email protected] %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

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

find -type f -printf '%[email protected] %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10

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

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];
    }'

Если у вас есть 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], reverse=True))[:10]: print f'

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

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

82
Gilles

Вам не нужно 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]*; ...

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

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

или же

ls -1rt `find /wherever/your/file/hides -type f`
9
skippy1910

Расширяя ответ пользователя 195696 :

find . -type f -printf "%[email protected]\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 КиБ выделяются: на 1 символ - 1-9 ГБ, на 2 символа - 10-99 ГБ и т.д.


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

find . -type f -printf "%[email protected]\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{} приводит к тому, что вхождение {} заменяется аргументом, и newlines теперь являются разделителями аргументов (обратите внимание на пробелы в именах файлов выше).

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

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

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

6
Evgeni Sergeev

Вариант OS X ответа @ user195696:

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

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Без отметки времени:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    
3
user9399

Пытаться:

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

Но также полезно фильтровать данные по -mmin/-mtime и -type.

1
Good.Dima

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

ls -1 *.cc # -r -t optional
1
djc

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

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
1
Bryan Petty

Использование:

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
Akash

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

0
Jim Lewis

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

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
jan

Вы можете использовать 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
drewk

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

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

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
0
john smith