Для общих имен файлов
find /some_folder/ -name "file_prefix*" -mtime +30 -printf '%TD %TT %p\n' |
sort |
awk '{if ($1==prevdate) print $3; prevdate=$1}' |
xargs rm
Команда find
выведет %TD %TT %p
, т.е. дату последней модификации, за которой следует время последней модификации, а затем путь к файлу (папка и имя файла).
Список отсортирован по sort
. Из-за структуры дата / время / путь к файлу это будет отсортировано по дате, а затем по времени, так что сначала печатаются самые старые файлы, что важно после.
awk
анализирует каждую строку и вызывает {if ($1==prevdate) print $3; prevdate=$1}
. Из-за структуры дата / время / путь к файлу дата равна $1
, время - $2
, а путь к файлу - $3
. Это печатает путь к файлу всякий раз, когда дата похожа на ранее проанализированную дату. Таким образом, первый файл дня не распечатывается, поскольку его дата отличается от даты предыдущего дня, и все последующие файлы того же дня печатаются. Обратите внимание, что prevdate
изначально не назначен, что примерно эквивалентно пустой строке. Вы можете вызвать это, если найдете его более читабельным:
awk 'BEGIN{prevdate=""} {if ($1==prevdate) print $3; prevdate=$1}'
Наконец, xargs rm
будет вызывать rm
для каждой строки из стандартного ввода, которое в данный момент содержит список файлов, напечатанных с помощью awk
.
Обработка пробелов
Если ваши имена файлов содержат пробелы, решение может быть слегка скорректировано:
find /some_folder/ -name "file_prefix*" -mtime +30 -printf '%TD %TT %p\n' |
sort |
awk '{if ($1==prevdate) print; prevdate=$1}' |
cut -d ' ' -f3- |
xargs rm
awk
печатает всю строку вместо печати только пути к файлу, затем имя файла извлекается с помощью cut -d ' ' -f3-
перед вызовом xargs rm
.
Обработка странных имен файлов
Приведенные выше решения не работают с именами файлов, содержащими переводы строки и, возможно, не будут работать с обратными слешами.
Я предполагаю, что вы не столкнетесь с этими проблемами, потому что если вы хотите очистить каталог, скорее всего, вы уже знаете, что находится в этом каталоге, и это возможно, файлы журналов или файлы другого типа, созданные автоматически.
Однако, если вам нужно обработать все типы имен файлов, приведенная ниже команда выполнит команду rick:
unset prevdate currentdate filepath
find /some_folder/ -name "file_prefix*" -mtime +30 -printf '%TD %TT %p\0' |
sort -z |
while IFS= read -r -d '' line
do
currentdate=${line%% *}
if [ "$currentdate" = "$prevdate" ]
then
filepath=$(cut -d ' ' -f3- <<< $line)
rm -- "$filepath"
fi
prevdate=$currentdate
done
По сути, он ведет себя как исходное решение, но строки разделяются нулевым символом (который является запрещенным символом в имени файла) вместо традиционного разделения новой строки.
find
выводит результаты с %TD %TT %p\0
вместо %TD %TT %p\n
, что означает, что результаты разделены нулями, тогда sort -z
использует этот разделенный нулями результат, и, наконец, while
l oop является перезаписью * Сценарий 1053 *, но использует строки, разделенные нулями (что практически невозможно сделать с awk
). В xargs rm
нет вызова, потому что rm
вызывается непосредственно внутри while
l oop.
Хотя возможность обрабатывать все типы имен файлов заманчива, обратите внимание, что это решение значительно менее эффективны, чем другие решения. Код, который я написал, неоптимален для образовательных целей, но он все равно будет медленнее, даже если я его оптимизирую.
Та же дата и время
Если несколько «первый файл дня» происходят в одно и то же время в течение одного дня, пропускается только первый файл с «наименьшим» путем к файлу, т.е. отсортированный по алфавиту c символов. Если вы хотите сохранить все первые файлы дня в одно и то же время, это немного сложнее, но это выполнимо.