Найти последний файл по дате изменения

Если я хочу найти последний файл (mtime) в (большой) каталог, содержащий подкаталоги, как бы это сделать?

Множество сообщений, которые я нашел, предлагает некоторые варианты ls -lt | head (забавно, многие предлагают ls -ltr | tail, что то же самое, но менее эффективно), что прекрасно, если у вас нет подкаталогов (я это делаю).

Затем вы можете

find . -type f -exec ls -lt \{\} \+ | head

который определенно сделает трюк за столько файлов, которые могут быть указаны одной командой, т. е. если у вас есть . Если я хочу найти последний файл (mtime) в (большом) каталоге, содержащем подкаталоги, как бы я это сделал это каталог , -exec...\+ выдаст отдельные команды; поэтому каждая группа будет сортироваться по ls внутри себя, но не по всему набору; поэтому руководитель заберет самую последнюю запись первой партии.

Любые ответы?

1
задан 17 January 2014 в 08:10

5 ответов

У меня была аналогичная проблема сегодня, но я атаковал ее без find. Мне нужно было что-то короткое, чтобы я мог запустить ssh, чтобы вернуть последний отредактированный файл в моем домашнем каталоге. Это примерно то, что я придумал:

ls -tp | grep -v /$ | head -1

Параметр -p для ls добавляет конечную косую черту в каталоги, grep -v удаляет строки, заканчивающиеся на косую черту (ака, все каталоги ), а head -1 ограничивает вывод в один файл.

Это гораздо менее подробный, чем использование find, если все, что вы хотите вернуть, - это имя файла.

6
ответ дан 25 May 2018 в 18:52

Это в моей системе быстрее, чем printf, хотя я не понимаю, почему

find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
3
ответ дан 25 May 2018 в 18:52
  • 1
    Я подтверждаю, что это быстрее. – enzotib 13 September 2011 в 14:58
  • 2
    Еще один момент, ... | sort -r | head -n1 | cut -d " " -f 4-, если вы хотите получить только имя файла. – 林果皞 19 April 2016 в 13:54
  • 3
    Я только что обнаружил, что sort -r будет ошибочным, если существует имя файла в нескольких строках. – 林果皞 19 April 2016 в 14:03

Это не так уж и модно, но это также возможно достичь с помощью Midnight Commander: поиск *, отображение результата, сортировка по времени модификации в обратном порядке.

Очевидно, что это немного медленнее, чем find - мой домашний каталог, содержащий 922000 файлов, был отсортирован по mc почти за 14 минут, в то время как find потратил меньше 5 - но есть некоторые преимущества:

Я, вероятно, потрачу дольше то разница в 9 минут придумывает правильный вызов на поиск :) меньше шансов на ошибку (забыл указать -r для сортировки и т. д. - начать снова), можно играть с результирующим набором, изменяя порядок сортировки и т. д. - без повторного запроса файлы. возможно выполнять операции с файлами только на некоторых файлах из набора результатов, т. е. сортировать по размеру, удалять несколько больших файлов, которые не нужны
1
ответ дан 25 May 2018 в 18:52

EDIT: Я думаю, этот пост не «не очень полезен», как я и думал. Это действительно быстрое решение, которое просто отслеживает последний измененный файл (вместо сортировки всего списка файлов):

find . -type f -printf '%T@ %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = $0; } } END { print mostrecentline; }' | cut -f2- -d ' '

Распространение на несколько строк для ясности он выглядит следующим образом:

find . -type f -printf '%T@ %p\n' | awk '
    BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; }
    {
        if ($1 > mostrecenttime)
            { mostrecenttime = $1; mostrecentline = $0; }
    }
    END { print mostrecentline; }' | cut -f2- -d ' '

Конец EDIT

Не особенно полезный пост, но так как «устраивать» обсуждали скорость, я думал, d).

Решения аранжировки и enzotib включают перечисление всех файлов внутри каталога с их mtimes, а затем сортировку. Как вы знаете, сортировка не нужна, чтобы найти максимум. Найти максимум можно в линейном времени, но сортировка занимает n log (n) time [Я знаю, что разница не много, но все же;)]. Я не могу придумать аккуратный способ реализации этого. [EDIT: опрятная (хотя и грязно выглядящая) и быстрая реализация, предусмотренная выше.]

Следующее лучшее - найти самый последний отредактированный файл в каталоге, рекурсивно найти последний отредактированный файл на каждом уровне 1 подкаталог. Пусть этот файл представляет собой подкаталог. Теперь отсортируйте файлы уровня 1 вместе с представителями подкаталогов уровня 1. Если число файлов и поддиректоров уровня 1 каждого каталога почти равно константе, то этот процесс должен масштабироваться линейно с общим количеством файлов.

Это то, что я придумал для реализации этого :

findrecent() { { find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1; }
findrecent .

Я запустил это и получил кучу ошибок find: findrecent: No such file or directory. Причина: -exec find работает в другой оболочке. Я попытался определить findrecent в .bashrc, .xsessionrc, но это не помогло [я буду признателен за помощь здесь]. В конце я прибегал к установке

#!/bin/bash
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

в скрипте под названием findrecent в моем PATH и затем его запуске.

Я запускал это, продолжал ждать и ждать без вывода , Чтобы быть уверенным, что у меня не было никаких бесконечных циклов, я изменил файл на

#!/bin/bash
echo "$1" >&2
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

и попытался снова.

Так много для превосходства O (n) по сравнению с O (n log (n)), но это заняло 1 минуту 35 секунд в моей домашней папке - решения arr и enzotib заняли 1,69, 1,95 секунды! )! Черт побери! [Или, скорее, накладные расходы на скрипт]

Но этот скрипт действительно масштабируется лучше, чем предыдущие, и я уверен, что он будет работать быстрее, чем в банке памяти Google, D

1
ответ дан 25 May 2018 в 18:52

Используйте perl в conjonctin с find:

 find my_directory -type f -printf '%T@\t%p\n' | perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'

Вы получите имя файла с наибольшей эпохой == последний файл изменен.

1
ответ дан 25 May 2018 в 18:52

Другие вопросы по тегам:

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