Вопрос или проблема
Каков сценарий использования команды find для сортировки поддерева в файлы с самым последним временем изменения? Также сохраняя их путь?
Я подозреваю, что это связано с find, ls, awk и sort. Я не видел, чтобы этот вопрос задавали здесь. Желательно использовать только инструменты в стиле BSD в ответе, а не Linux.
Команда find
имеет директиву -printf
, форматные опции которой включают оператор %T@
, который выводит время последней модификации с момента эпохи (возможны другие форматы). Это можно отсортировать с помощью обратных числовых опций, а затем отредактировать с помощью sed
или awk
.
Если есть вероятность, что некоторые из ваших имен файлов могут включать символ новой строки, вам нужно использовать символ \0
для завершения формата и использовать опцию -z
в sort
.
find ./Toshiba -type f -printf '%T@|%p\n' | sort -rn | sed -e 's/^[^|]*|//'
find
не сортирует файлы¹.
ls
может сортировать файлы по времени модификации, но если вы выполните:
find subtree -exec ls -td {} +
И если список файлов слишком велик, чтобы уместиться в лимит размера аргументов+переменных окружения, которые передаются команде, то это приведет к выполнению нескольких вызовов ls
, которые будут сортироваться независимо.
Самым простым вариантом было бы использовать zsh
, чьи глобалы могут выполнять почти все, что может выполнять find
, и сортировать список по разным критериям, включая время последней модификации:
print -rC1 -- subtree/**/*(NDom)
Или передать другой команде в таком порядке:
print -rNC1 -- subtree/**/*(NDom) | xargs -r0 another command
Или просто:
another command subtree/**/*(NDom)
Если список достаточно мал, чтобы поместиться в один вызов внешней команды.
Измените o
на O
, чтобы изменить порядок на обратный (и сделать самыми первыми старые файлы).
Или вы можете использовать perl
для сортировки:
find subtree -print0 | perl -MTime::HiRes=lstat -l -0e '
print $_->[1] for sort {$b->[0] <=> $a->[0]} map {[(lstat$_)[9], $_]} <>'
Или передать другой команде:
find subtree -print0 | perl -MTime::HiRes=lstat -0le '
print $_->[1] for sort {$b->[0] <=> $a->[0]} map {[(lstat$_)[9], $_]} <>' |
xargs -r0 another command
Поменяйте местами $a
и $b
, чтобы изменить порядок на обратный.
Если вы можете гарантировать, что ни один путь к файлу не содержит каталогов с новой строкой (хотя на практике ни одна из известных мне UNIX-подобных систем этого не запрещает), вы можете использовать команду BSD stat
, чтобы вывести метку времени с точностью до субсекунд:
find subtree -exec stat -f %Fm%t%N {} + |
LC_ALL=C sort -rn |
cut -f2-
Чтобы передать другой команде:
find subtree -exec stat -f %Fm%t%N {} + |
LC_ALL=C sort -rn |
cut -f2- |
LC_ALL=C tr '\n' '\0' |
xargs -r0 another command
Удалите опцию -r
из sort
, чтобы изменить порядок на обратный.
Обратите внимание, что файлы, которые невозможно lstat()
, будут пропущены.
Если, как предполагают ваши другие недавние вопросы, ваш “BSD” на самом деле является Solaris 10 (который вы уже спутали с BSD), ваш лучший выбор среди них, вероятно, подходы zsh (так как в Solaris 10 есть zsh; версия с 20 летней историей, но достаточно новая для этой цели), хотя учтите, что в xargs Solaris 10 нет поддержки опций -r
и -0
(которые были добавлены только в выпущенном в 2024 году стандарте POSIX).
Из другого оболочки:
zsh -c 'print -rC1 -- subtree/**/*(NDom)'
zsh -c 'another command subtree/**/*(NDom)'
Или если список слишком велик, используйте автозагружаемую функцию zsh zargs
вместо сильно ограниченного xargs
из Solaris:
zsh -c 'autoload zargs; zargs subtree/**/*(NDom) -- another command'
¹ Ну, строго говоря, вы можете обнаружить, что некоторые реализации find
внутренне сортируют записи каталогов по номерам inode в попытке уменьшить количество перемещений головки на вращающихся жёстких дисках.
Установите dust и выберите желаемый порядок отображения или сортировки.
.
Ответ или решение
Для решения задачи сортировки поддерева файлов по времени последнего изменения, сохраняя их путь, необходимо применить подход, который сочетает использование командных инструментов Unix, таких как find
, sort
, awk
, и потенциально других утилит. Но прежде всего, стоит рассмотреть концепции и теорию, лежащие в основе предложенного решения, чтобы понять, почему те или иные шаги необходимы.
Теоретическая часть
Для сортировки файлов или других данных по определенному критерию, в нашем случае по времени последнего изменения, необходимо представление каждого файла вместе с его временной меткой. Это означает, что мы должны собрать данные о всех файлах, включая их пути и временные метки, а затем применить сортировку на основе этих меток.
Команда find
в Unix-подобных системах часто используется для поиска и выполнения операций над файловым деревом. Она позволяет фильтровать файлы по различным критериям, а также поддерживает использование формата для вывода, который может включать временные метки. Однако сама по себе find
не осуществляет сортировку файлов.
Команда sort
используется для сортировки входящих данных. Она может принимать различные параметры, такие как сортировка по числовому значению или в обратном порядке.
Практический пример
Рассмотрим конкретный пример. Для начала мы будем использовать команду find
для получения списка файлов с временными метками:
find ./subtree -type f -printf '%T@|%p\n'
Здесь %T@
возвращает время последней модификации файла с точностью до секунд эпохи UNIX, а |%p
добавляет разделитель перед путем файла.
Полученные данные сортируются с использованием sort
, учитывая опцию -r
для сортировки в обратном порядке (по убыванию):
find ./subtree -type f -printf '%T@|%p\n' | sort -rn
После сортировки нам нужно убрать часть строки, содержащую временные метки. Это можно сделать с помощью утилиты sed
:
find ./subtree -type f -printf '%T@|%p\n' | sort -rn | sed -e 's/^[^|]*|//'
Этот конвейер обеспечит нам список файлов, отсортированных по времени модификации от самых новых к наиболее старым.
Зачем это нужно и как применять
Этот подход позволяет не только получить представление о том, какие файлы в вашей системе были недавно изменены, но также и автоматизировать процесс при мониторинге изменений в файловой системе. Это может быть использовано для резервного копирования только тех файлов, которые были обновлены, или для мониторинга разработок в коде, где важно отслеживать последние изменения.
Кроме того, такая техника может быть применена в различных сценариях, требующих аудита изменений, например, в административной практике или при разработке ПО, где критически важна сохранность и отслеживание версии файлов.
Таким образом, интеграция инструментов find
, sort
и sed
предоставляет мощное средство для работы с большими объемами данных о файловой системе, обеспечивая эффективный и гибкий подход к управлению и анализу данных. Используя стандартные инструменты Unix, вы можете достичь высокой производительности и надежности без необходимости в установке дополнительных приложений.
Помимо рассмотренного метода, существует множество других подходов и инструментов, таких как zsh
с его расширенными возможностями работы с файлами, или использование perl
для более сложной обработки данных. Выбор инструмента может зависеть от конкретных потребностей и ограничений вашей системы.