Подтвердить что ты не робот

Shell script для подсчета файлов, а затем удалить старые файлы

Я новичок в shell-скриптах, поэтому мне нужна помощь здесь. У меня есть каталог, который заполняет резервные копии. Если у меня есть более 10 файлов резервных копий, я бы хотел удалить самые старые файлы, чтобы оставить только 10 самых последних файлов резервных копий.

До сих пор я знаю, как подсчитывать файлы, что кажется достаточно простым, но как я могу удалить старые файлы, если счетчик превышает 10?

if [ls /backups | wc -l > 10]
    then
        echo "More than 10"
fi
4b9b3361

Ответ 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 '{}'"