Linux удалить все файлы кроме последних

3 способа удалить все файлы в каталоге, кроме одного или нескольких файлов с расширениями

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

В этой статье мы покажем вам, как удалять файлы в каталоге, кроме определенных расширений или типов файлов, с помощью команд rm, find и globignore.

Прежде чем мы двинемся дальше, давайте начнем с краткого рассмотрения одной важной концепции Linux — сопоставления имен файлов с образцом, которая позволит нам решить нашу проблему.

В Linux шаблон оболочки представляет собой строку, состоящую из следующих специальных символов, которые называются подстановочными знаками или метасимволами:

  1. * — соответствует нулю или более символов
  2. ? — соответствует любому одиночному символу
  3. [seq] — соответствует любому символу в seq
  4. [!seq] — соответствует любому символу, не указанному в seq

Здесь мы рассмотрим три возможных метода, в том числе:

Удаление файлов с помощью расширенных операторов сопоставления с образцом

Различные расширенные операторы сопоставления с образцом перечислены ниже, где список-шаблонов — это список, содержащий одно или несколько имен файлов, разделенных символом | :

  1. *(список-шаблонов) — соответствует нулю или более вхождений указанных шаблонов
  2. ?(список-шаблонов) — соответствует нулю или одному вхождению указанных шаблонов
  3. +(список-шаблонов) — соответствует одному или нескольким вхождениям указанных шаблонов
  4. @(pattern-list) — соответствует одному из указанных шаблонов
  5. !(список-шаблонов) — соответствует чему угодно, кроме одного из заданных шаблонов

Чтобы использовать их, включите параметр оболочки extglob следующим образом:

1. Чтобы удалить все файлы в каталоге, кроме имени файла, введите следующую команду:

2. Чтобы удалить все файлы, кроме filename1 и filename2:

3. В приведенном ниже примере показано, как удалить все файлы, кроме всех файлов .zip , в интерактивном режиме:

4. Затем вы можете удалить все файлы в каталоге, кроме всех файлов .zip и .odt , следующим образом, отображая то, что сделанный:

Получив все необходимые команды, отключите параметр оболочки extglob следующим образом:

Удалить файлы с помощью команды поиска Linux

В этом методе мы можем использовать команду find исключительно с соответствующими параметрами или в сочетании с командой xargs, используя конвейер, как в формах ниже:

$ find /directory/ -type f -not -name 'PATTERN' -delete $ find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I <> rm <> $ find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I <> rm [options] <>

5. Следующая команда удалит все файлы, кроме файлов .gz в текущем каталоге:

$ find . -type f -not -name '*.gz'-delete

6. Используя конвейер и xargs, вы можете изменить приведенный выше случай следующим образом:

$ find . -type f -not -name '*gz' -print0 | xargs -0 -I <> rm -v <>

7. Рассмотрим еще один пример. Приведенная ниже команда удалит все файлы, кроме .gz , .odt и . .jpg файлы в текущем каталоге:

$ find . -type f -not \(-name '*gz' -or -name '*odt' -or -name '*.jpg' \) -delete

Удалить файлы с помощью переменной Bash GLOBIGNORE

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

Читайте также:  Linux получить размер терминала

Чтобы использовать этот метод, перейдите в каталог, который вы хотите очистить, затем установите переменную GLOBIGNORE следующим образом:

$ cd test $ GLOBIGNORE=*.odt:*.iso:*.txt

В этом случае все файлы, кроме файлов .odt , .iso и .txt , будут удалены из текущего каталога.

Теперь запустите команду для очистки каталога:

После этого отключите переменную GLOBIGNORE:

Примечание. Чтобы понять значение флагов, используемых в приведенных выше командах, обратитесь к справочным страницам каждой команды, которую мы использовали на различных иллюстрациях.

Вот и все! Если у вас есть какие-либо другие методы командной строки для той же цели, не забудьте поделиться с нами через наш раздел обратной связи ниже.

Источник

удалить все файлы кроме последних 70 — скрипт, как?

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

Способов можно придумать много.

1. Натравить на эти файлы logrotate или любой другой аналогичный инструмент.

2. Если нужно чтобы работал однострочник из примера выше и он удалял 70 последних файлов, то я поправил бы его так:

ls -1 -r log_fileflow*.txt |head -n -70|xargs rm -rf 2>&1 /BackUp/backuprm.txt

3. Если у тебя реально пишутся логи со скоростью 6 файлов в час то можно сделать однострочник на find примерно такого вида и перенаправить его вывод в какой-то файл:

find $path_2dir_with_garbage -mtime +12H -name «log_fileflow*.txt» -exec rm -v <> \;

Имхо, разумнее всего для этой цели использовать утилиты для ротации логов и не пихать в крон костыли, про которые потом не вспомнить.

Сорри, пока редактировал свой ответ уже все по делу написали:)

2. Если нужно чтобы работал однострочник из примера выше и он удалял 70 последних файлов, то я поправил бы его так:

надо чтобы он оставлял, а не удалял последние 70 файлов.

вызыватся будет не с крона, а из самого скрипта, который по циклу замкнут.

кстати, xargs rm -rf 2>&1 /BackUp/backuprm.txt- сиё логирование тоже не работает, то есть backuprm.txt даже не создаётся.

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

А это самый правильный вариант. Там очень просто описать в конфиге все условия, которые тебе необходимы. Ещё и всякие дополнительные возможности есть типа архивирования, post-rotate команд и прочего.

кстати, xargs rm -rf 2>&1 /BackUp/backuprm.txt- сиё логирование тоже не работает, то есть backuprm.txt даже не создаётся.

А должен? И что вы в нем увидеть хотели?

рабочий проверенный скрипт. можт кому пригодитося

#!/bin/bash cd /PD_nfs/MEOS echo $(date) ##define variables address="email@email.com" #ls -ltr | tail -n1 | awk '' #find /data -type f -mmin 20 -exec stat -c '%Y %n %y' <> + | sort -k1nr | head -1 while true; do COUNT=$(find . -mmin -10 -type f | wc -l) echo $(pwd); echo $(date); echo "last file date: " $(ls -ltr | tail -n1 | awk ''); find . -mmin -10 -type f | wc -l ; timestamp=$(date +%Y%m%d_%H%M%S) path="/Second" filename=log_check_flow_$timestamp.txt log=/Second/$filename START_TIME=$(date +%s) END_TIME=$(date +%s) ELAPSED_TIME=$(expr $END_TIME - $START_TIME) find . -mmin -10 -type f | wc -l >> $log; find . -mmin -10 -type f | head -n15 |tee -a $log echo "find output for 20 minutes : " >> $log find . -type f -mmin 20 -exec stat -c '%Y %n %y' <> + | sort -k1nr | head -1 >> $log echo " " >> $log echo " ls -ltr output: " >> $log ls -ltr | tail -n1 | awk '' >> $log #remove old logfiles: pwd date >>$path/log_rm.txt; ls -t -r $path/log_check*.txt |head -n -70 ls -t -r $path/log_check*.txt |head -n -70 |xargs rm -rfv >>$path/log_rm.txt; #ls -t -r $path/log_check*.txt |tail -n +18 |xargs rm -rfv >$path/log_rm.txt; echo "remove_old_logfiles pass" #echo "Backup :: Script End -- $(date +%Y%m%d_%H%M)" >> $log echo "Checking :: Script End -- $(date +%Y%m%d_%H%M)" >> $log echo "Elapsed Time :: $(date -d 00:00:$ELAPSED_TIME +%Hh:%Mm:%Ss) " >> $log # check for rm logfile size: echo "rm_log size now is: " du $path/log_rm.txt | cut -f1 if [[ $(du $path/log_rm.txt | cut -f1) -gt 100 ]]; then echo 're-arm log_rm'; cp $path/log_rm.txt $path/log_rm.old; :>$path/log_rm.txt fi if [ $COUNT = 0 ]; then #ACHTUNG. last=$(ls -ltr | tail -n1 | awk ''); body=" Admin, we have problems on SER2! last incoming files was: $last" ; echo -e $body | mail -S smtp=214.50.70.11 -S from=outgoing@email.com -s "Warning on SER2" -c email2@email.com $address; fi sleep 360 done; 

Источник

Читайте также:  User log files in linux

Как удалить все, кроме 10 новейших файлов в Linux?

Я пытаюсь держать каталог, полный файлов журнала, управляемым. Ночью я хочу удалить все, кроме 10 самых последних. Как я могу сделать это в одной команде?

@ovaherenow «твой»? Я не вижу твоего имени ни в одном вопросе, поэтому не уверен, что ты имеешь в виду. Мой комментарий даже не указывает, что является дубликатом другого. Но это не имеет значения — это просто комментарий со ссылкой. Его можно добавить либо к вопросу, либо к обоим вопросам. Это зависит от кого-то еще — администратора — чтобы пометить один или другой как дубликат. Никакой гнусной ловкости не было и не должно быть. Более важным, чем вопрос был первым, является вопрос, какой из них имеет лучший ответ — опять же, ссылка облегчает эту дискуссию, но не определяет ответ.

@ Майкл вау. Это действительно странно. Эта тема была открыта мной, но это явно не мое имя пользователя. Но я получаю уведомление об этой теме.

Для портативного и надежного решения, попробуйте это:

ls -1tr | head -n -10 | xargs -d '\n' rm -f -- 

tail -n -10 Синтаксис в одном из других ответов , кажется , не работать везде (то есть, не на моих системах RHEL5).

И использование $() или « в командной строке rm рискует

  1. разделение имен файлов пробелами и
  2. превышение максимального ограничения символов командной строки.

xargs устраняет обе эти проблемы, потому что он автоматически выяснит, сколько аргументов он может передать в пределах ограничения на количество символов, и при этом -d ‘\n’ он будет разбиваться только на границе строки ввода. Технически это все еще может вызвать проблемы для имен файлов с новой строкой в ​​них, но это гораздо реже, чем имена файлов с пробелами, и единственный способ обойти новые строки будет намного сложнее, вероятно, с использованием по крайней мере awk, если не perl.

Читайте также:  Astra linux kyocera driver

Если у вас нет xargs (возможно, старых систем AIX?), Вы можете сделать это циклом:

ls -1tr | head -n -10 | while IFS= read -r f; do rm -f "$f" done 

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

@HaukeLaging: со head(1) страницы руководства : -n, —lines=[-]K print the first K lines instead of the first 10; with the leading ‘-‘, print all but the last K lines of each file

На Солярисе 10 head и xargs выдают ошибки. Правильные варианты есть head -n 10 и xargs rm -f . Полная команда ls -1tr ./ | head -n 10 | xargs rm -rf

Следует также отметить, что переводы строки — это редкие, но допустимые символы в именах файлов ext. Это означает, что если у вас есть файлы «тот» и «тот \ nthing», если этот скрипт ударит «тот \ nthing», он удалит «тот», ошибку, когда он не смог удалить «вещь», и оставит «что \ nthing» (предполагаемая цель) не затрагивается.

Код, который вы хотите включить в свой скрипт

 rm -f $(ls -1t /path/to/your/logs/ | tail -n +11) 

Опция -1 (числовая) печатает каждый файл в одной строке, чтобы быть в безопасности. -f Вариант rm говорит , что игнорировать файлы несуществующие для того, когда ls возвращает ничего.

Оригинальный постер, здесь. Я попробовал эту команду, но она не работает — я получаю сообщение об ошибке «rm: отсутствующий операнд»

Вы использовали правильный путь? Очевидно, /path/to/your/logs это просто сделано для вас, чтобы ввести правильный путь. Для того, чтобы найти ошибку выполнения частей ls -t /path/. и в ls -t /path/. | tail -n +11 одиночку , и проверить , если результат является правильным.

@HaukeLaging Я совершенно уверен, что вы что-то не так поняли. Следите + за числом. Он tail печатает не последние n элементов, а все элементы, начиная с n-го. Я зарегистрировался снова, и команда должна обязательно удалить только элементы старше 10 самых последних файлов при любых обстоятельствах.

Я думаю, что ваш ответ очень опасен, ls печатает имя файла, а не путь, поэтому вы rm -f будете пытаться удалить файлы в текущем каталоге

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

find /path/to/files -mtime 10 -delete 

Или, если каждый файл создан произвольно:

find /path/to/files -maxdepth 1 -type f -printf '%Ts\t%P\n' | sort -n | head -n -10 | cut -f 2- | xargs rm -rf 

-mtime 10 -delete удаляет только файлы, измененные ровно 10 дней назад. Старые файлы не будут удалены. -mtime +11 -delete удалит файлы, которые были изменены 11 или более дней назад, оставив последние 10 дней файлов журнала.

Я думаю, что использование %p вместо %P необходимо для того, printf чтобы файлы получили полный путь. В противном случае rm -rf не работает.

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

Источник

Оцените статью
Adblock
detector