Unix / Linux знаходять і сортують за датою зміни


138

Як я можу зробити простий, findякий упорядкував би результати за останніми зміненими?

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

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

Як я міг зробити це замовлення на пошук за останніми зміненими? (Зауважте, я не хочу, щоб він сортував "після" пошуку, а скоріше знаходити результати на основі того, що було нещодавно змінено.)


github.com/shadkam/recentmost зробить те, що бажається - але потрібно будувати це
user3392225

Відповіді:


153

Використовуй це:

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: Ім'я файлу.


5
+1 Дуже корисно, першу відповідь на це я знайшов із прочитаним / корисним результатом дати
Джейк N

найнадійніший (і дуже простий), оскільки час має бути послідовно числовим (тому завжди правильно сортується), thx!
Сила Водолія

1
У мене є цей псевдонім для пошуку останніх файлів у моєму ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }він рекурсивно знаходить усі файли, що містять шаблон першого аргументу, переданого команді ( fr <pattern>), і сортує їх з останнім останнім.
joelostblom

Це чудово !!! Щоб користуватися символьними посиланнями, використовуйтеfind -L ...
Варун Чандак

1
Ви можете скористатися, ssedщоб позбутися секундної дробової частини та стилю використання ISO8601, як @PeterMortensen показав:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty

83

Найпростіший метод - використовувати zsh, завдяки його глобальним класифікаторам .

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

Якщо ви знайдете GNU, змусьте його надрукувати часові зміни файлів і відсортувати їх.

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

Якщо у вас є GNU, але не інші утиліти 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 - це легка частина)


Я думаю, що findверсія показує найдавніші файли, і вам потрібно додати цю -rопцію sort.
Квентін Прадет

Мій sed каже, що він не має опції -z.
Кеф Шектер

@KefSchecter Потім використовуйте нові рядки як роздільники, але ви втратите підтримку нових рядків у назвах файлів.
Жиль

Сказане вище стосується python2. Якщо у вас є лише python3, деякі невеликі зміни: python3 -c 'import os, sys; times = {} для f в sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime для f in (відсортовано (times.keys (), key = lambda f: times [f], reverse = True)) [: 10]: print (f); '
Ніл Макгілл

40

Вам не потрібно 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 . -print0|xargs -0 command (оптимізує швидкість, якщо find не реалізує "-exec +", але знає "-print0")
  • find . -print|xargs command (якщо в аргументах немає пробілу)

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


1
Якщо файлів багато, це не вдається зі списком аргументів занадто довгим на ls.
окулус

1
Це правда, але я вважаю, що питання було "як мені зробити просту знахідку ..."
Ярослав Рахматуллін

2
ls не цитує імена файлів таким чином, щоб xargs могли зрозуміти (немає варіанту -0, а різні стилі цитат неадекватні)
Tobu

10

Вам потрібні лише ls

Ви можете зробити так, find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;як зазначено вище,

або

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

2
Якщо файлів багато, це не вдається зі списком аргументів занадто довгим на ls. Можливо, відновіть використання xargs?
окулус

2
Але якщо xargsдзвінки lsкілька разів, сортування буде порушено.
Аарон Д. Мараско

Це не вдається для файлів з пробілами в їх назвах. Будь-яка порада?
user74094

Я просто натрапив на цю відповідь, і це було саме те, що мені було потрібно в подібній ситуації. Питання: що робить +;в кінці? Здається, це дає такий же результат, ;однак без цього не виходить +?
RocketNuts

Це точно так само, як і інша відповідь, опублікована за 8 місяців до цього, за винятком частини про використання "ls -1rt` find ... `", яка порушена
Clément

7

Розширення відповідь user195696 в :

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

Для кожного файлу спочатку виводиться цифрова часова марка (для сортування за подальшим підрахунком \t), потім для людини, прочитаної часовою міткою, потім розмір файлів (на жаль find, -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 ГБ, на 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 сортувати за часом, що тут не має значення, але я зазвичай використовую це.


1
Примітка: для сортування файлів розміром замість цього, просто замінити свій T@шлях sв будь-якому із зазначених вище команд.
Євгеній Сергєєв

3

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

2

Я виявив, що це робить роботу на Mac OS X (і достатньо загальної для роботи на інших Unixen):

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

2
На жаль, це друкує локалізовані назви місяців у моїй хорватській програмі, роблячи сортування неправильним.
Іван Вучиця

Відповідь користувача195696 працює для налаштування Хорватії (та інших).
Пітер Мортенсен

1

Якщо ваш findвибір дуже простий, ви можете обійтися без нього, а просто скористайтеся ls:

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

1

Спробуйте:

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

Але також корисно фільтрувати дані за -mmin/ -mtimeі -type.


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

Я поліпшив цей sript обробляти прогалини в іменах файлів, див superuser.com/a/777007/134532
JAN

1

У мене є просте рішення, яке працює як для FreeBSD (OS X), так і для Linux:

find . -type f -exec ls -t {} +

Це прекрасно працює - має бути правильна відповідь або принаймні більш високий рейтинг!
digitaltoast

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

Якщо ви хочете замовити всі файли PNG за часом у $PWD:

Цей простий один вкладиш забезпечує всю гнучкість регулярних виразів на findі ls.

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

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

Існує чистий та надійний спосіб sort | headна сьогодні:

Використання ls -lдля симпатичного друку

find . ! -type d -printf "%T@ %p\0" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.]\+ //' |
    xargs -0 ls -lt

Як функція :

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

Це може бути запущено з одним або двома аргументами або навіть без:

Usage: findByDate [-h] [lines] [find options]

Зразок:

findByDate

Буде перераховано всі не каталоги, відсортовані за датою. Нота:

Навіть у великому дереві файлових систем, як xargs отримують вже відсортований список, порядок файлів залишається правильним, навіть якщо його lsпотрібно виконувати багато разів.

findByDate -h 12

Буде перелічено ще 12 прийомів, які не містять каталогів, відсортовані за датами, розмір яких надрукований у читаному для людини вигляді

findByDate 42 '-type l'

Буде вказано ще 42 символи посилань

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

Буде перераховано всі посилання, блокувати пристрої, розетки та пристрої символів, відсортовані за датою.

Інвертування порядку

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

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

Та ж функція, те саме використання:

Usage: findByDate [-h] [lines] [find options]

-1

Якщо ви просто хочете отримати повний шлях кожного елемента, ви можете записати так.

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

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


cut -d ' ' -f 2порушиться, якщо в назви файлів містяться пробіли.
Ф. Хаурі

-3

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

Після cdдо каталогу, використовуйте

find . -iname "*" -ls


1
Це не сортувати за датою зміни.
DavidPostill
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.