Как удалить файлы из папки с более чем 60 файлами в unix?

Я хочу поставить скрипт в cronjob, который будет запускаться в определенное время, и если количество файлов больше 60, оно удалит старые файлы из этой папки. Последний в первый раз. Я пытался,

#!/bin/ksh for dir in /home/DABA_BACKUP do cd $dir count_files=`ls -lrt | wc -l` if [ $count_files -gt 60 ]; then todelete=$(($count_files-60)) for part in `ls -1rt` do if [ $todelete -gt 0 ] then rm -rf $part todelete=$(($todelete-1)) fi done fi done 

Это все файлы резервных копий, которые сохраняются ежедневно и имеют имя backup_$date . Это нормально?

5 Solutions collect form web for “Как удалить файлы из папки с более чем 60 файлами в unix?”

Нет, с одной стороны, он будет разбит на имена файлов, содержащие новые строки. Это также более сложно, чем необходимо, и имеет все опасности разбора ls .

Лучшая версия будет (с использованием инструментов GNU):

 #!/bin/ksh for dir in /home/DABA_BACKUP/* do ## Get the file names and sort them by their ## modification time files=( "$dir"/* ); ## Are there more than 60? extras=$(( ${#files[@]} - 60 )) if [ "$extras" -gt 0 ] then ## If there are more than 60, remove the first ## files until only 60 are left. We use ls to sort ## by modification date and get the inodes only and ## pass the inodes to GNU find which deletes them find dir1/ -maxdepth 1 \( -inum 0 $(\ls -1iqtr dir1/ | grep -o '^ *[0-9]*' | head -n "$extras" | sed 's/^/-o -inum /;' ) \) -delete fi done 

Обратите внимание, что это предполагает, что все файлы находятся в одной файловой системе и могут давать неожиданные результаты (например, удаление неправильных файлов), если они не являются. Он также не будет работать, если есть несколько жестких ссылок, указывающих на один и тот же индекс.

 #! /bin/zsh - for dir (/home/DABA_BACKUP/*) rm -f $dir/*(Nom[61,-1]) 

Для zsh-невежественного ;-):

  • for var (list) cmd : короткая версия for var in list; do cmd; done for var in list; do cmd; done (напоминает синтаксис perl ).
  • $dir : переменные zsh не нужны, как и в других оболочках, поскольку zsh имеет явные glob split и glob поэтому не делает неявный split + glob при расширении параметра.
  • *(...) : glob с квалификаторами glob :
  • N : nullglob : glob не увеличивает ничего, а не создает ошибку, если она не соответствует.
  • m : создавать сгенерированные файлы в момент опускания (младший сначала).
  • [61,-1] : из этого упорядоченного списка выберите 61-й и последний.

Таким образом, в основном удаляются все, кроме 60 самых младших файлов.

Чтобы получить список самых старых записей для удаления (таким образом, сохраняя 60 последних записей):

 ls -t | tail -n +61 

Обратите внимание, что принципиальная проблема вашего подхода еще не решена и здесь: как обрабатывать файлы с символами новой строки, если это имеет значение; в противном случае вы можете просто использовать (заменив довольно сложную программу):

 cd /home/DABA_BACKUP || exit 1 ls -t | tail -n +61 | xargs rm -rf 

Примечание. Кажется, что у вас есть ежедневные резервные копии, возможно, вы также можете использовать подход, основанный на дате и find файлов; как в:

 find /home/DABA_BACKUP -mtime +60 -exec ls {} + 

(где команда ls – после тщательного изучения правильной работы! – должна быть заменена соответствующей командой rm ).

 rm60()( IFS=/; set -f; set $( set +f; \ls -1drt ./*) while shift && [ $# -gt 60 ] do [ -d "${1%?.}" ] || rm "./${1%?.}" || exit done ) 

Это будет работать для вас. Он удалит самые старые файлы в текущем каталоге до 60. Он будет делать это путем синтаксического разбора ls и будет делать это без каких-либо предположений о ваших именах файлов – их можно назвать чем угодно и их не нужно называть датами , Это будет работать только для списка текущего каталога, и в случае, если у вас установлен POSIX ls (и не замаскирован какой-либо злой функцией оболочки, но описаны alias ) .

Вышеприведенное решение просто применяет очень простое разделение оболочки на некоторые очень простые пути к Unix. Он гарантирует, что ls перечисляет все неточечные файлы в текущем каталоге по одному на строку, например:

 ./oldestfile ./second-oldestfile 

Теперь любой из них может иметь перемычки между ними, но это не проблема. Потому что в этом случае они будут перечислены как:

 ./oldest file ./s econd old est file ./third 

…и так далее. И новые строки нас не беспокоят, потому что мы не разделяем их. Почему мы должны? Мы работаем с / pathnames, мы должны разделить на разделитель пути, и это то, что мы делаем: IFS=/ .

Теперь это немного странно. Мы закончим список аргументов, который выглядит так:

 <.> <file1\n.> <file2\n.> ... <filelast> 

… но это на самом деле очень хорошо для нас, потому что мы можем отложить наши аргументы, обрабатываемые оболочкой как файлы (или, в случае, если мы хотим избежать, символические ссылки), пока мы не будем готовы их использовать.

Поэтому, когда у нас есть наш список файлов, все, что нам нужно сделать, это shift наш первый аргумент, убедитесь, что у нас в настоящее время имеется более 60 аргументов, возможно, снижается до rm каталога (хотя, конечно, это полностью зависит от вы) , и в противном случае rm наш первый аргумент меньше его последних двух символов. Нам не нужно беспокоиться о последнем последнем аргументе, который не имеет приложенного периода, потому что мы никогда туда не попадаем и вместо этого выходим на 60. Если мы сделали это так далеко для итерации, тогда мы просто попробуем еще раз и перебираем список arg таким образом, пока мы не обрезаем его для нашего удовлетворения.

Как это ломается? По-моему, это не так, но я разрешил это – если в любой момент произойдет непредвиденная ошибка, цикл прерывается, а функция возвращает значение, отличное от 0.

И поэтому ls может сделать вашу запись для вас в текущем каталоге без каких-либо проблем. Вы можете надежно разрешить ему сортировать свои аргументы для вас, если вы можете надежно их разграничить. Именно по этой причине это не будет работать так, как написано ни о чем, кроме текущего каталога. Для более одного разделителя в строке пути потребуется еще один уровень разграничения, который можно было бы сделать, умножив его дважды для всех, кроме последнего в поля NUL , но сейчас я не хочу этого делать.

Если вы знаете, все файлы называются backup_ *, вы должны включить это в команду ls, поэтому вы обрабатываете только те, а не файлы, которые случайно попадают в каталог. Затем ls используется в трубе, он отображает только 1 файл на строку, а затем только подсчет, не нужно сортировать, поэтому

 count_files=$(ls -U backup_* | wc -l) 

а также

 for part in $(ls -rt backup_*);do rm -rf "$part" todelete=$(($todelete-1)) if [[ $todelete -eq 0 ]]; then break fi done 
  • Определение, является ли файл жесткой ссылкой или символической ссылкой?
  • regex удалить последние четыре символа
  • Если #head versionnumber.txt <#head lastversionnumber.txt, то: сделайте это
  • вкладки в переменной не работают
  • Терминал Ubuntu закрывается после запуска скрипта
  • Почему этот скрипт рыбы не запускается из пусковой установки?
  • Как получить двоичные представления строк в Shell?
  • Сценарий оболочки для изменения каталога терминала и открытия второго терминала
  • Сохранить кешированное видео на firefox?
  • проблема сценария оболочки с использованием операторов
  • Ловушка, ERR и повторение строки ошибки
  • Interesting Posts

    Проблемы с сетевым подключением к немаршрутизирующим многодомным хостам?

    Как сделать файлы внутри TMPFS более вероятными для обмена

    Как понять команду awk '{for (x = 1; $ x; ++ x) print $ x}'?

    файл библиотеки найден ldconfig, но не ldd

    Отключить звуковой сигнал в lightdm

    Как запустить полную проверку SSD-диска командой `fsck` при перезагрузке системы (Debian)?

    как отредактировать следующую строку после сопоставления шаблона и добавить строку, если она не существует

    Как заставить yaourt устанавливать все обновления

    Как настроить Xen GPU для моего AMD Radeon GPU?

    Настройка sendmail как реле для интернет-провайдера

    Массовое устройство хранения не смонтировано

    Сценарий для перемещения одного типа файлов и создания подпапки, если он существует?

    Как получить завершение bash для псевдонимов команд?

    Что означает -o означает «если»?

    Как может команда монтирования сбой в одном окне терминала, но не в другом?

    Linux и Unix - лучшая ОС в мире.