Удаление всего, кроме новейших файлов

8

Допустим, у меня есть каталог, ḟoo/который содержит много файлов в некоторой структуре каталогов. Мне нужно сохранить некоторые из них, но не все.

Есть ли способ (на месте) удалить их всех, кроме, скажем, 500 новейших?

Далибор Карлович
источник

Ответы:

11

Я делаю эту задачу регулярно, и я использую варианты следующего. Это конвейер, объединяющий различные простые инструменты: найдите все файлы, добавьте время модификации файла, отсортируйте, удалите время изменения файла, отобразите все строки, кроме первых 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"'
Питер Джон Аклам
источник
Я был бы осторожен с rm -fхотя.
CVN
Работает как шарм! Это должно быть доступно как псевдоним с параметрами $ path и $ count. Большое спасибо!
Далибор Карлович
4

Вот как я бы сделал это в 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)
jftuga
источник
4

Я не знаю насчет «500 новейших», но с помощью find вы можете удалить вещи, которые старше X минут / дней. Пример для файла и старше 2 дней:

find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;

Сначала проверьте с:

find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;

Следите за обратным слешем и пробелом перед "\;". См. Страницу поиска для получения дополнительной информации.

AndreasM
источник
«(Скажем) 500 новейших» является суть здесь, поэтому я не вижу, как это отвечает на первоначальный вопрос.
Питер Джон Аклам
Извините, мне было непонятно.
AndreasM
3

если бы вы могли хранить файлы х дней / часов вместо новейшего х числа, вы могли бы сделать это просто с tmpwatch --ctime 7d

Sirex
источник
2

Я думаю, что -mtimeи -newerпараметры findкоманды полезны для вас. Вы можете увидеть man findдля получения дополнительной информации.

Халед
источник
0

почему бы не использовать этот более простой код:

$ ls -t1 foo/| xargs -d '\n' rm --
eppesuig
источник
1
Как это удалить все файлы, кроме 500 самых последних файлов? И как это обрабатывает подкаталоги? Я думаю, что вы, возможно, неправильно поняли оригинальную публикацию.
Питер Джон Аклам