Допустим, у меня есть каталог, ḟoo/который содержит много файлов в некоторой структуре каталогов. Мне нужно сохранить некоторые из них, но не все.
Есть ли способ (на месте) удалить их всех, кроме, скажем, 500 новейших?
Допустим, у меня есть каталог, ḟoo/который содержит много файлов в некоторой структуре каталогов. Мне нужно сохранить некоторые из них, но не все.
Есть ли способ (на месте) удалить их всех, кроме, скажем, 500 новейших?
Ответы:
Я делаю эту задачу регулярно, и я использую варианты следующего. Это конвейер, объединяющий различные простые инструменты: найдите все файлы, добавьте время модификации файла, отсортируйте, удалите время изменения файла, отобразите все строки, кроме первых 500, и удалите их:
find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
sort -r | cut -c14- | tail -n +501 | \
while read file; do rm -f -- "$file"; done
Несколько комментариев:
Если вы используете «bash», вы должны использовать «read -r file», а не «read file».
Использование «perl» для удаления файлов выполняется быстрее (а также обрабатывает «странные» символы в именах файлов лучше, чем цикл while, если только вы не используете «read -r file»):
... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
Некоторые версии «tail» не поддерживают опцию «-n», поэтому вы должны использовать «tail +501». Портативный способ пропустить 500 первых строк
... | perl -wnle 'print if $. > 500' | ...
Это не будет работать, если ваши имена файлов содержат переводы строк.
Это не требует GNU найти.
Сочетание вышесказанного дает вам:
find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
sort -r | cut -c14- | perl -wnle 'print if $. > 500' | \
perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
Вот как я бы сделал это в Python 3., который также должен работать для других ОС. После тестирования убедитесь, что раскомментируйте строку, которая фактически удаляет файлы.
import os,os.path
from collections import defaultdict
FILES_TO_KEEP = 500
ROOT_PATH = r'/tmp/'
tree = defaultdict(list)
# create a dictionary containing file names with their date as the key
for root, dirs, files in os.walk(ROOT_PATH):
for name in files:
fname = os.path.join(root,name)
fdate = os.path.getmtime( fname )
tree[fdate].append(fname)
# sort this dictionary by date
# locate where the newer files (that you want to keep) end
count = 0
inorder = sorted(tree.keys(),reverse=True)
for key in inorder:
count += len(tree[key])
if count >= FILES_TO_KEEP:
last_key = key
break
# now you know where the newer files end, older files begin within the dict
# act accordingly
for key in inorder:
if key < last_key:
for f in tree[key]:
print("remove ", f)
# uncomment this next line to actually remove files
#os.remove(f)
else:
for f in tree[key]:
print("keep ", f)
Я не знаю насчет «500 новейших», но с помощью find вы можете удалить вещи, которые старше X минут / дней. Пример для файла и старше 2 дней:
find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;
Сначала проверьте с:
find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;
Следите за обратным слешем и пробелом перед "\;". См. Страницу поиска для получения дополнительной информации.
почему бы не использовать этот более простой код:
$ ls -t1 foo/| xargs -d '\n' rm --
rm -fхотя.