Shell script для подсчета файлов, а затем удалить старые файлы
Я новичок в shell-скриптах, поэтому мне нужна помощь здесь. У меня есть каталог, который заполняет резервные копии. Если у меня есть более 10 файлов резервных копий, я бы хотел удалить самые старые файлы, чтобы оставить только 10 самых последних файлов резервных копий.
До сих пор я знаю, как подсчитывать файлы, что кажется достаточно простым, но как я могу удалить старые файлы, если счетчик превышает 10?
if [ls /backups | wc -l > 10]
then
echo "More than 10"
fi
Ответы
Ответ 1
Попробуйте следующее:
ls -t | sed -e '1,10d' | xargs -d '\n' rm
Это должно обрабатывать все символы (кроме строк новой строки) в имени файла.
Что здесь происходит?
-
ls -t
перечисляет все файлы в текущем каталоге в порядке убывания времени модификации. То есть, последние измененные файлы сначала, одно имя файла в строке.
-
sed -e '1,10d'
удаляет первые 10 строк, т.е. 10 самых новых файлов. Я использую это вместо tail
, потому что я не могу вспомнить, нужна ли мне tail -n +10
или tail -n +11
.
-
xargs -d '\n' rm
собирает каждую строку ввода (без завершающей строки новой строки) и передает каждую строку в качестве аргумента rm
.
Как и в любом другом подобном случае, пожалуйста, экспериментируйте в безопасном месте.
Ответ 2
Правильный способ сделать этот тип вещей - logrotate
.
Ответ 3
find
- общий инструмент для такого рода задач:
find ./my_dir -mtime +10 -type f -delete
ПОЯСНЕНИЕ
-
./my_dir
ваш каталог (замените его собственным)
-
-mtime +10
старше 10 дней
-
-type f
только файлы
-
-delete
неудивительно. Удалите его, чтобы протестировать ваш фильтр find
перед выполнением всей команды
И будьте уверены, что ./my_dir
существует, чтобы избежать неприятных сюрпризов!
Ответ 4
Убедитесь, что ваш pwd является правильным каталогом для удаления файлов (при условии, что в имени файла используются только обычные символы):
ls -A1t | tail -n +11 | xargs rm
хранит новейшие 10 файлов. Я использую это с программой камеры "motion", чтобы сохранить самые последние файлы захвата кадров. Спасибо всем исходящим ответам, потому что вы показали мне, как это сделать.
Ответ 5
Мне нравятся ответы от @Dennis Williamson и @Dale Hagglund. (+1 к каждому)
Здесь другой способ сделать это с помощью find
(с тестом -newer
), который похож на то, с чего вы начали.
Это было сделано в bash на cygwin...
if [[ $(ls /backups | wc -l) > 10 ]]
then
find /backups ! -newer $(ls -t | sed '11!d') -exec rm {} \;
fi
Ответ 6
Простой счетчик файлов:
max=12
n=0
ls -1t *.dat |
while read file; do
n=$((n+1))
if [[ $n -gt $max ]]; then
rm -f "$file"
fi
done
Ответ 7
stat -c "%Y %n" * | sort -rn | head -n +10 | \
cut -d ' ' -f 1 --complement | xargs -d '\n' rm
Разбивка. Получайте последние изменения для каждого файла (в формате "time
filename
" ), сортируйте их от самых старых до новейших, сохраняйте все, кроме последних десяти записей, а затем сохраняйте все, кроме первого поля (сохраняйте только часть имени файла).
Изменить: использование cut
вместо awk
, поскольку последнее не всегда доступно
Изменить 2: теперь обрабатывает имена файлов с пробелами
Ответ 8
В очень ограниченной среде chroot у нас было только несколько программ, доступных для достижения того, что изначально было задано. Мы решили это так:
MIN_FILES=5
FILE_COUNT=$(ls -l | grep -c ^d )
if [ $MIN_FILES -lt $FILE_COUNT ]; then
while [ $MIN_FILES -lt $FILE_COUNT ]; do
FILE_COUNT=$[$FILE_COUNT-1]
FILE_TO_DEL=$(ls -t | tail -n1)
# be careful with this one
rm -rf "$FILE_TO_DEL"
done
fi
Объяснение:
-
FILE_COUNT=$(ls -l | grep -c ^d )
подсчитывает все файлы в текущей папке. Вместо grep мы могли бы использовать также wc -l
, но wc не был установлен на этом хосте.
-
FILE_COUNT=$[$FILE_COUNT-1]
обновить текущий $FILE_COUNT
-
FILE_TO_DEL=$(ls -t | tail -n1)
Сохраните самое старое имя файла в переменной $FILE_TO_DEL
. tail -n1
возвращает последний элемент в списке.
Ответ 9
Использование номеров inode с помощью команды stat и find (чтобы избежать проблем с pesky-chars-in-file-name):
stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -print
#stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
# xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -delete
Ответ 10
Поэкспериментируйте с этим, потому что я не уверен на 100%, что он будет работать:
cd /backups; ls -at | tail -n +10 | xargs -I{} "rm '{}'"