Как мне подсчитать количество файлов в каталоге и удалить самые старые, если число превышает 5

Всегда можно:

ps -eLo pid= -o tid= | awk '$2 == 792 {print $1}'

В Linux:

$ readlink -f /proc/*/task/792/../..
/proc/300

Или сzsh:

$ echo /proc/*/task/792(:h:h:t)
300
14
04.02.2020, 12:21
6 ответов

Вы можете посмотреть на set -- /home/backup/databasebk_*и, пока $#больше пяти, удалить файл.

Таким образом, код будет похож на

set -- /home/backup/databasebk_*
while [ $# -gt 5 ]
do
  echo "Removing old backup $1"
  rm "$1"
  shift
done

Это работает, потому что имена файлов, которые вы выбрали, автоматически располагаются в порядке «сначала старые».

Для согласованности я бы установил переменную (Обычно я называю ее BASE, но вы можете называть ее как хотите)

Итак,

BASE=/home/backup/databasebk_
FILE=${BASE}!`date +"%Y-%m-%d_%H:%M"`.sql
....
set -- ${BASE}*
while [ $# -gt 5 ]
do
  echo "Removing old backup $1"
  rm "$1"
  shift
done
12
28.04.2021, 23:24
files=( /home/backup/* )
# files is now an array containing file names in the directory

oldest=""
if (( ${#files[@]} > 5 ))  ## are there more than five?
then 
  for name in "${files[@]}" ## loop to find oldest
  do
    a=$( stat --printf=%Y "$name" )
    if  [ -z "$oldest" ] || (( a < age ))
    then 
       age="$a"
       oldest="$name"
    fi
  done
  rm "$oldest"
fi

Некоторые комментарии:

Я говорю /home/backup/*, что находит все файлы в этом каталоге Вместо этого я мог бы сказать /home/backup/databasebk_*.sql.gz, чтобы просто найти сжатые дампы

.

Я использую 'stat', чтобы найти самый старый файл в соответствии с файловой системой поскольку ваши даты указаны в порядке формата YMDhm, я мог бы вместо этого сравнить имена файлов

 if  [ -z "$oldest" ] || [ "$name" -lt "$oldest" ]

наличие подкаталогов в /home/backup/ нарушит этот скрипт

2
28.04.2021, 23:24

Я думаю, что лучше использовать logrotate, так как это приложение уже выполняет действия, которые вы пытаетесь выполнить с помощью своего скрипта. Я протестировал следующие скрипты на своем тестовом сервере.

  1. Создайте резервную копию базы данных вручную. Это необходимо, поскольку logrotate не запустится, если файл не существует.
    $ mysqldump -uroot -pmy5trongpass database > mydatabase.sql
    $ ls
    $ mydatabase.sql

Пример ошибки, если первая база данных не была создана.

    #**logrotate -f** will force our new rule to run now and backup the database
    #this is for testing purposes.

    $ logrotate -f /etc/logrotate.d/mysql_backup
    error: stat of /home/backups/mydatabase.sql failed: No such file or directory
  1. Создайте файл/правило logrotate. Вот тот, который я создал на основе других правил, находится в /etc/logrotate.d/
    $ cat /etc/logrotate.d/mysql_backup
    /home/backups/mydatabase.sql{
            create 640 root mysql
           daily
            rotate 2
            nocompress
        postrotate
            mysqldump -uroot -pmy5trongpass test > mydatabase.sql;
            echo "done"
        endscript
    }
  1. Проверьте конфигурацию с помощью
$ logrotate -f /etc/logrotate.d/mysql_backup
$ logrotate -f /etc/logrotate.d/mysql_backup
done
$ ll
total 16
-rw-r-----. 1 root mysql 1261 Feb  3 21:46 mydatabase.sql
-rw-r-----. 1 root mysql 1261 Feb  3 21:44 mydatabase.sql.1
-rw-r-----. 1 root mysql 1261 Feb  3 21:44 mydatabase.sql.2

вы увидите, что будет создан новый файл, за которым следует номер, который можно изменить, чтобы отображались даты, используя следующие параметры

https://linux.die.net/man/8/logrotate

dateext
Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number. The extension may be configured using the dateformat option.

dateformat format_string
Specify the extension for dateext using the notation similar to strftime(3) function. Only %Y %m %d and %s specifiers are allowed. The default value is -%Y%m%d. Note that also the character separating log name from the extension is part of the dateformat string. The system clock must be set past Sep 9th 2001 for %s to work correctly. Note that the datestamps generated by this format must be lexically sortable (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). This is because when using the rotate option, logrotate sorts all rotated filenames to find out which logfiles are older and should be removed.
12
28.04.2021, 23:24

Использование оболочки zsh:

rm -f /home/backup/databasebk_*.sql.gz(.om[6,-1])

Это создаст список путей к обычным файлам, соответствующим /home/backup/databasebk_*.sql.gz, отсортирует список по меткам времени модификации файлов (, которые были изменены последними первыми ), и извлечет элементы с 6 по конец. Затем эти файлы будут переданы в rm -fдля удаления.

Это квалификатор glob , (.om[6,-1])в конце шаблона подстановки имени файла, который определяет обычные файлы (.), упорядочение по времени модификации (om), и что должно быть возвращено с 6-го по последнее совпадение ([6,-1]).

6
28.04.2021, 23:24

В чистом Bash без циклов:

ls -t | tail -n +6 | xargs -d '\n' rm

Пояснение:

  • ls -tвыводит все файлы в текущем каталоге, отсортированные по времени модификации, сначала самые новые.
  • tail -n +6игнорирует первые 5 строк и печатает строки 6 и далее.
  • xargs -d '\n' rmудаляет переданные ему файлы, по одному в строке. Если вы абсолютно уверены, что в именах файлов нет пробелов или кавычек, вы можете использовать просто xargs rm.

Обратите внимание, что это удаляет столько файлов, сколько необходимо, чтобы оставить только 5 файлов в каталоге. Если вы хотите удалить только один самый старый файл, замените +6на 1.

19
28.04.2021, 23:24

Создатьrm-except-last.sh:

#!/bin/bash -

set -o nounset

if ! (($#)); then
  echo Usage: "$BASH_SOURCE" N_NOT_TO_DELETE FILES_TO_DELETE...
  exit 1
fi

declare N="${1:?Missing N_NOT_TO_DELETE.}"
if ! [[ "$N" =~ ^[0-9]+$ ]]; then
  echo 1>&2 -E Not a number: "$N"
  exit 1
fi
shift

declare -a roll=()
while ((${#roll[@]} < N)); do
  roll+=('')
done

if ! ((N)); then
  rm -rfv -- "$@"
  exit $?
fi

declare n=0 file=''
for file in "$@"; do
  declare rmfile="${roll[n]}"
  [ -n "$rmfile" ] && rm -rfv -- "$rmfile"
  roll[n]="$file"
  ((n = (n + 1) % N))
done

Тогда:

$ rm-except-last.sh 5 /home/backup/databasebk_*.sql

1
28.04.2021, 23:24

Теги

Похожие вопросы