- 3 способа удалить все файлы в каталоге, кроме одного или нескольких файлов с расширениями
- Удаление файлов с помощью расширенных операторов сопоставления с образцом
- Удалить файлы с помощью команды поиска Linux
- Удалить файлы с помощью переменной Bash GLOBIGNORE
- удалить все файлы кроме последних 70 — скрипт, как?
- Как удалить все, кроме 10 новейших файлов в Linux?
3 способа удалить все файлы в каталоге, кроме одного или нескольких файлов с расширениями
Иногда вы попадаете в ситуацию, когда вам нужно удалить все файлы в каталоге или просто очистить каталог, удалив все файлы, кроме файлов заданного типа (оканчивающихся определенным расширением).
В этой статье мы покажем вам, как удалять файлы в каталоге, кроме определенных расширений или типов файлов, с помощью команд rm, find и globignore.
Прежде чем мы двинемся дальше, давайте начнем с краткого рассмотрения одной важной концепции Linux — сопоставления имен файлов с образцом, которая позволит нам решить нашу проблему.
В Linux шаблон оболочки представляет собой строку, состоящую из следующих специальных символов, которые называются подстановочными знаками или метасимволами:
- * — соответствует нулю или более символов
- ? — соответствует любому одиночному символу
- [seq] — соответствует любому символу в seq
- [!seq] — соответствует любому символу, не указанному в seq
Здесь мы рассмотрим три возможных метода, в том числе:
Удаление файлов с помощью расширенных операторов сопоставления с образцом
Различные расширенные операторы сопоставления с образцом перечислены ниже, где список-шаблонов — это список, содержащий одно или несколько имен файлов, разделенных символом | :
- *(список-шаблонов) — соответствует нулю или более вхождений указанных шаблонов
- ?(список-шаблонов) — соответствует нулю или одному вхождению указанных шаблонов
- +(список-шаблонов) — соответствует одному или нескольким вхождениям указанных шаблонов
- @(pattern-list) — соответствует одному из указанных шаблонов
- !(список-шаблонов) — соответствует чему угодно, кроме одного из заданных шаблонов
Чтобы использовать их, включите параметр оболочки 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 хранит разделенный двоеточиями список шаблонов (имен файлов), которые следует игнорировать при раскрытии пути.
Чтобы использовать этот метод, перейдите в каталог, который вы хотите очистить, затем установите переменную 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;
Как удалить все, кроме 10 новейших файлов в Linux?
Я пытаюсь держать каталог, полный файлов журнала, управляемым. Ночью я хочу удалить все, кроме 10 самых последних. Как я могу сделать это в одной команде?
@ovaherenow «твой»? Я не вижу твоего имени ни в одном вопросе, поэтому не уверен, что ты имеешь в виду. Мой комментарий даже не указывает, что является дубликатом другого. Но это не имеет значения — это просто комментарий со ссылкой. Его можно добавить либо к вопросу, либо к обоим вопросам. Это зависит от кого-то еще — администратора — чтобы пометить один или другой как дубликат. Никакой гнусной ловкости не было и не должно быть. Более важным, чем вопрос был первым, является вопрос, какой из них имеет лучший ответ — опять же, ссылка облегчает эту дискуссию, но не определяет ответ.
@ Майкл вау. Это действительно странно. Эта тема была открыта мной, но это явно не мое имя пользователя. Но я получаю уведомление об этой теме.
Для портативного и надежного решения, попробуйте это:
ls -1tr | head -n -10 | xargs -d '\n' rm -f --
tail -n -10 Синтаксис в одном из других ответов , кажется , не работать везде (то есть, не на моих системах RHEL5).
И использование $() или « в командной строке rm рискует
- разделение имен файлов пробелами и
- превышение максимального ограничения символов командной строки.
xargs устраняет обе эти проблемы, потому что он автоматически выяснит, сколько аргументов он может передать в пределах ограничения на количество символов, и при этом -d ‘\n’ он будет разбиваться только на границе строки ввода. Технически это все еще может вызвать проблемы для имен файлов с новой строкой в них, но это гораздо реже, чем имена файлов с пробелами, и единственный способ обойти новые строки будет намного сложнее, вероятно, с использованием по крайней мере awk, если не perl.
Если у вас нет 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, сделает это за вас. Это делает управление журналами намного проще. Вы также можете включить дополнительные процедуры очистки, такие как предложенный гало.