Если я захочу найти последний файл (mtime) в (большом) каталоге, содержащем подкаталоги, как бы я это сделал?
Множество найденных сообщений предлагают некоторые вариант ls -lt | head
(забавно, многие предлагают ls -ltr | tail
, который такой же, но менее эффективный), что хорошо, если у вас нет подкаталогов (у меня есть).
Опять же, вы могли бы
find . -type f -exec ls -lt \{\} \+ | head
, что определенно сделает трюк для столько файлов, сколько может быть указано одной командой, то есть, если у вас есть большой каталог , [ 113] будет выдавать отдельные команды; поэтому каждая группа будет отсортирована по ls
внутри себя, но не по общему набору; Таким образом, головка подхватит последнюю запись первой партии.
Есть ответы?
У меня была похожая проблема сегодня, но я атаковал ее без find
. Мне нужно было что-то короткое, чтобы я мог запустить ssh
, чтобы вернуть последний отредактированный файл в моем домашнем каталоге. Это примерно то, что я придумал:
ls -tp | grep -v /$ | head -1
Опция -p
для ls
добавляет косую черту в каталоги, grep -v
удаляет строки, заканчивающиеся косой чертой (иначе все каталоги) и head -1
ограничивает вывод одним файлом.
Это гораздо менее многословно, чем использование find
, если все, что вы хотите вернуть - это имя файла.
Вам не нужно возвращаться к внешним командам (как ls
), потому что find
может сделать все, что вам нужно, с помощью действия -printf
:
find /path -printf '%T+ %p\n' | sort -r | head
find . -type f -exec stat --format=%y \{\} \+ | sort -r | head -n1
, но Вашим решением является намного инструмент для очистки!
– steev
05.05.2020, 09:19
Это не так модно, но этого также можно достичь с помощью Midnight Commander : поиск *, группировка результатов, сортировка по времени изменения в обратном порядке.
Очевидно, это немного медленнее, чем find
- мой домашний каталог, содержащий 922000 файлов, был отсортирован по mc
почти за 14 минут, в то время как find
потратил меньше 5 - но есть некоторые преимущества:
Вероятно, я бы потратил больше, чем разница в 9 минут, придумывая правильный вызов find:)
меньше шансов на ошибку (забыл указать -r для сортировки и т. д. - начните заново)
можно воспроизвести набор результатов, изменив порядок сортировки и т. д. - без повторного запроса файлов.
можно выполнять файловые операции только над некоторыми файлами из результирующего набора, то есть сортировать по размеру, удалять несколько больших файлов, которые не нужны
Используйте perl
в сочетании с find
:
find my_directory -type f -printf '%T@\t%p\n' | perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'
Вы получите имя файла с наибольшей эпохой == последний измененный файл.
Это в моей системе быстрее, чем printf
, хотя я не понимаю, почему
find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
... | sort -r | head -n1 | cut -d " " -f 4-
, если Вы хотите получить имя файла только.
– naught101
05.05.2020, 09:21
sort -r
, будет неправильно, если имя файла через несколько строк будет существовать.
– gareth
05.05.2020, 09:22
РЕДАКТИРОВАТЬ: я думаю, что этот пост не «не особенно полезен», как я думал, что это было. Это действительно быстрое решение, которое просто отслеживает последний измененный файл (вместо сортировки всего списка файлов):
find . -type f -printf '%T@ %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = [114]; } } 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 = [110]; }
}
END { print mostrecentline; }' | cut -f2- -d ' '
Конец РЕДАКТИРОВАНИЯ
Не особенно полезный пост, но, так как «аранжировка» обсуждала скорость, я решил поделиться этим.
Решения компоновки и энзотиба включают перечисление всех файлов в каталоге с их mtimes, а затем сортировку. Как известно, сортировка не нужна, чтобы найти максимум. Найти максимум можно за линейное время, но сортировка занимает n log (n) времени [я знаю, разница невелика, но все же;)]. Я не могу придумать изящный способ реализации этого. [РЕДАКТИРОВАТЬ: аккуратная (хотя и грязная на вид) и быстрая реализация, представленная выше.]
Следующая лучшая вещь - чтобы найти самый последний отредактированный файл в каталоге, рекурсивно найдите самый последний отредактированный файл в каждом подкаталоге уровня 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;
и попытался снова. Это сработало - но заняло 1 минуту 35 секунд в моей домашней папке - решения аранжировки и энзотиба заняли 1,69 и 1,95 секунды соответственно!
Так много для превосходства O (n) над O (n log (n)) ! Черт возьми, функция вызова накладных расходов! [Или, скорее, издержки вызова сценария]
Но этот сценарий масштабируется лучше, чем предыдущие решения, и я уверен, что он будет работать быстрее, чем они, в банке памяти Google; D