112

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

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

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

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

16 ответов16

117

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

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

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

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

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

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

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

80

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

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

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

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

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

find -type f -printf '%T@ %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 является легкой частью).

36

Вам не нужен 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

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

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

или же

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

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

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

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

Затем 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 "%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 сортирует по времени, что здесь неактуально, но это то, что я обычно использую.

2

Вариант 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) }'
    
1

Пытаться:

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

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

1

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

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

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

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

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

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
0

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

0

Я улучшил ответ 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

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

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

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

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

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

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

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

-3

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

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

find . -iname "*" -ls

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .