Bash команда удалить все, кроме последних 5 каталогов
Возможный дубликат:
Удалить все, кроме последних X файлов в bash
У меня есть script для создания инкрементных резервных копий ежедневно, и мне нужно удалить все резервные копии, но последние 5.
Например, у меня есть следующие папки:
drwxr-xr-x 4 root root 4096 Oct 29 01:10 2010-10-29
drwxr-xr-x 4 root root 4096 Oct 30 01:10 2010-10-30
drwxr-xr-x 4 root root 4096 Oct 31 01:10 2010-10-31
drwxr-xr-x 4 root root 4096 Nov 1 01:10 2010-11-01
drwxr-xr-x 4 root root 4096 Nov 2 01:10 2010-11-02
drwxr-xr-x 4 root root 4096 Nov 3 01:10 2010-11-03
drwxr-xr-x 4 root root 4096 Nov 4 01:10 2010-11-04
drwxr-xr-x 4 root root 4096 Nov 5 01:10 2010-11-05
drwxr-xr-x 4 root root 4096 Nov 6 01:10 2010-11-06
drwxr-xr-x 4 root root 4096 Nov 7 01:10 2010-11-07
drwxr-xr-x 4 root root 4096 Nov 8 01:10 2010-11-08
И мне нужно поддерживать только последние 5 каталогов и удалять остальные. После выполнения команды мне нужно иметь только это:
drwxr-xr-x 4 root root 4096 Nov 4 01:10 2010-11-04
drwxr-xr-x 4 root root 4096 Nov 5 01:10 2010-11-05
drwxr-xr-x 4 root root 4096 Nov 6 01:10 2010-11-06
drwxr-xr-x 4 root root 4096 Nov 7 01:10 2010-11-07
drwxr-xr-x 4 root root 4096 Nov 8 01:10 2010-11-08
Мне не нужно удалять предыдущие 5 дней, мне нужно удалить все, кроме 5 последних каталогов:)
Теперь я использую:
find /backup/increment -maxdepth 1 -type d -mtime +5 -exec rm -rf {} \;
Но мне нужно совершенствоваться не вовремя:)
EDIT:. Это пример для сервера, который делает резервные копии в течение всего дня, но мне нужен script, который удаляет все папки, предшествующие последним 5, потому что мой компьютер делает резервные копии в 00:10 на ночь, но не все ночи резервное копирование сделано, потому что мой компьютер не работает все дни, и мне нужно иметь всегда последние 5 резервных копий:)
Ответы
Ответ 1
используйте команду tail
для печати строк, начинающихся с n-й строки (Option -n +N
):
rm `ls -t | tail -n +6`
ls -t
выводит текущий каталог, отсортированный по времени. tail -n +6
берет al строки, начиная с 6-й строки. Цитирование с backticks подает результат трубы в команду rm
.
OLD SOLUTION, не правильно...
используйте команду head
, которая печатает первые n строк некоторого вывода:
rm `ls -t1 | head -n 5`
ls -t
выводит текущий каталог, отсортированный по времени. head -n 5
берет первые пять записей предыдущего вывода. Цитирование с backticks подает результат трубы в команду rm
.
Пожалуйста, попробуйте сначала, прежде чем подать заявку на живые данные:)...
Ответ 2
Первое, что пришло мне в голову. Это не изящно:
a=0;
for i in `ls -t`;
do
a=`expr $a + 1`;
if [ $a -gt 5 ]; then
echo "removing $i";
rm -rf $i
fi;
done
Ответ 3
создать два фиктивных файла с началом и датой окончания
touch -t 1010290000 before
touch -t 2011042359 after
найти все файлы между двумя фиктивными файлами и "rm -rf" результат
find . -newer before \! -newer after -exec rm -rf {} \;
Ответ 4
ls -tr | perl -ne '{@files = < > ; print @files [0.. $# files-5]} '| xargs -n1 echo rm -rf
Вы должны удалить эхо перед rm -rf, чтобы заставить его работать.
Ответ 5
Трюк будет опцией -t для ls, которая сортирует по времени модификации от самого нового до самого старого.
На самом деле наивное решение, использующее временный файл, может идти следующим образом:
ls -t > /tmp/file_list
num_files_to_keep=5
# wc -l gets the line count of a file
# first word of wc output is the actual line count, and that all we need, so
# delete everything after the space.
num_files=`wc -l /tmp/file_list | sed "s/ .*//"`
#if appropriate you should add a check for num_files < num_files_to_keep
num_files_to_delete=$(( $num_files - $num_files_to_keep ))
rm `tail -n $num_files_to_delete /tmp/file_list`