Допустим, у меня есть каталог ḟ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», вам следует использовать «чтение -r файл», а не просто «чтение файла».
Использование «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 \{\} \;
Обратите внимание на обратную косую черту и пробел перед "\;". См. Справочную страницу find для получения дополнительной информации.
если бы вы могли хранить файлы старше x дней / часов вместо самого нового числа x, вы могли бы сделать это просто с tmpwatch --ctime 7d
я думаю -mtime
и -newer
варианты find
вам пригодятся. Ты можешь видеть man find
для получения дополнительной информации.
почему бы не использовать этот более простой код:
$ ls -t1 foo/| xargs -d '\n' rm --