Bash удалить файл с расширением
Is there a simple way, in a pretty standard UNIX environment with bash, to run a command to delete all but the most recent X files from a directory?
To give a bit more of a concrete example, imagine some cron job writing out a file (say, a log file or a tar-ed up backup) to a directory every hour. I'd like a way to have another cron job running which would remove the oldest files in that directory until there are less than, say, 5.
And just to be clear, there's only one file present, it should never be deleted.
112k 46 46 gold badges 107 107 silver badges 128 128 bronze badges16 Answers 16
The problems with the existing answers:
- inability to handle filenames with embedded spaces or newlines.
- in the case of solutions that invoke rm directly on an unquoted command substitution ( rm `. ` ), there's an added risk of unintended globbing.
wnoise's answer addresses these issues, but the solution is GNU-specific (and quite complex).
Here's a pragmatic, POSIX-compliant solution that comes with only one caveat: it cannot handle filenames with embedded newlines - but I don't consider that a real-world concern for most people.
Note: This command operates in the current directory; to target a directory explicitly, use a subshell ( (. ) ) with cd :
(cd /path/to && ls -tp | grep -v '/$' | tail -n +6 | xargs -I <> rm -- <>)
The same applies analogously to the commands below.The above is inefficient, because xargs has to invoke rm separately for each filename.
However, your platform's specific xargs implementation may allow you to solve this problem:A solution that works with GNU xargs is to use -d '\n' , which makes xargs consider each input line a separate argument, yet passes as many arguments as will fit on a command line at once:
Note: Option -r ( --no-run-if-empty ) ensures that rm is not invoked if there's no input.
A solution that works with both GNU xargs and BSD xargs (including on macOS) - though technically still not POSIX-compliant - is to use -0 to handle NUL -separated input, after first translating newlines to NUL ( 0x0 ) chars., which also passes (typically) all filenames at once:
Explanation:
ls -tp prints the names of filesystem items sorted by how recently they were modified , in descending order (most recently modified items first) ( -t ), with directories printed with a trailing / to mark them as such ( -p ).
- Note: It is the fact that ls -tp always outputs file / directory names only, not full paths, that necessitates the subshell approach mentioned above for targeting a directory other than the current one ( (cd /path/to && ls -tp . ) ).
grep -v '/$' then weeds out directories from the resulting listing, by omitting ( -v ) lines that have a trailing / ( /$ ).
- Caveat: Since a symlink that points to a directory is technically not itself a directory, such symlinks will not be excluded.
tail -n +6 skips the first 5 entries in the listing, in effect returning all but the 5 most recently modified files, if any.
Note that in order to exclude N files, N+1 must be passed to tail -n + .xargs -I <> rm -- <> (and its variations) then invokes on rm on all these files; if there are no matches at all, xargs won't do anything.
- xargs -I <> rm -- <> defines placeholder <> that represents each input line as a whole, so rm is then invoked once for each input line, but with filenames with embedded spaces handled correctly.
- -- in all cases ensures that any filenames that happen to start with - aren't mistaken for options by rm .
A variation on the original problem, in case the matching files need to be processed individually or collected in a shell array:
Что нужно: удаление файлов с определённым расширением из директории /home.
В /home может быть множество различных папок.
Файлов с разными расширениями может быть много.
BitSum ★★ ( 13.09.17 23:13:41 )
Последнее исправление: BitSum 13.09.17 23:13:48 (всего исправлений: 1)куча вариантов 1) на питоне напиши, расширения в кортеж, потом с помощью endswith() проверяешь файлы 2) на баше напиши 3) тупо возьми find
find ./ -type f \( -iname \*.txt -o -iname \*.iso \)
find -iregex '.*\.\(txt\|html\|iso\)$'
-exec позволяет выполнить команду, подставив найденное имя. '<>' — найденное имя, экранированная точка с запятой — конец блока -exec.
Добавил решения в первый пост.
Как создать переменную для указания расширений? Иначе получится колхоз.
у линуксового find есть сразу опция -delete
-exec универсальный :) А вникать в этот ман нужно очень долго.
Файлов с разными расширениями может быть много.
Забудь про расширения. Это вендузячий подход. В линуксах просто имя файла. Если точка в начале, то некоторые утилиты считают его скрытым.
А раз имя файла, то к нему можно применять регулярки. Например rm *bak
тип регулярки можно задать через -regextype, список типов получить запустив 'find -regextype help', но само их описание погребено в недрах info.
Как создать переменную для указания расширений?
bash таки умеет массивы.
Если позанудствовать, то ТСа можно понять так, что каталоги с именами типа a.txt/ удалять наверное не надо. :)
Если позанудствовать . каталоги с именами типа a.txt/ удалять наверное не надо
. -type f .
Так видно лучше? Никто и не собирался ^)А, точно, спать надо больше :( Как же так. Наверное прокоментировать хотел пример выше, а взял последнее.
vodz ★★★★★ ( 14.09.17 07:44:45 )
Последнее исправление: vodz 14.09.17 07:47:22 (всего исправлений: 1)А что, rm -r *.*ext* не катит уже?
1) нерекурсивный
2) на большом количестве файлов тянет на переполнение комстрокиТакой вариант ещё предложили, ну очень удобный.
Такой вариант ещё предложили, ну очень удобный.
Может выдать типа:
vodz ★★★★★ ( 14.09.17 09:12:28 )
Последнее исправление: vodz 14.09.17 09:13:52 (всего исправлений: 3)колхоз, но с утра голова лучше не придумала)
Заодно пометь тему решенной
колхоз, но с утра голова лучше не придумала)
эм, давно не баше не писал, пардноньте, а то, что я поставил точку перед расширением не поможет?
. прогнал у себя по хомяку, нет ни одного ошибочного совпадения.что я поставил точку перед расширением не поможет?
Нет, потому что маска развернется ещё в for i in *?[xyz]* <-- вот тут.
хм, спасибо, буду знать.
Так в итоге, какое конечное решение будет на баше? Чтобы я протестировал и обновил первый пост.
BitSum ★★ ( 14.09.17 11:54:08 )
Последнее исправление: BitSum 14.09.17 11:54:22 (всего исправлений: 1)
vodz ★★★★★ ( 14.09.17 11:59:48 )
Последнее исправление: vodz 14.09.17 12:02:48 (всего исправлений: 3)С переменными и, особенно, массивами в bash лучше не связывайся, с ними всегда больше ошибок и тормозов, типичный пример тут Удалить файлы с определённым расширением. Как? (комментарий)
С переменными и, особенно, массивами в bash лучше не связывайся
Я осилил. И понял, что, во-первых, оно того не стоит и почти везде лучше итерацию по пассиву заменять на пайпы, xargs и т.п. и во-вторых, новичок точно напорется на грабли с файликами с пробелами, начинающимися на минус, с длиной командной строки и т.п.
во-первых, оно того не стоит и почти везде лучше
И этот поц говорит о тормозах и пробелах в именах.
Обновил первый пост. Добавил скрипт на баше.
Пожалуй его и буду использовать. Наиболее компактный вариант для меня, с учётом того, что выражений десятки.
BitSum ★★ ( 14.09.17 12:56:01 )
Последнее исправление: BitSum 14.09.17 12:57:50 (всего исправлений: 2)Чтобы не выглядеть так как и вы голословным,
Вариант с итерацией по башевскому массиву проходит дерево столько раз, сколько ищется расширений - это может быть и 10 и 20 раз. Многократное замедление прохода по диску - это не голые слова, а суровая реальность. А через год ТС захочет решить те-же задачу тем-же способом, но забудет кавычки или поставит не те и будет удивляться, почему простой скрипт глючит.
Вариант с итерацией по башевскому массиву проходит дерево столько раз, сколько ищется расширений - это может быть и 10 и 20 раз.
Это вроде бы правильно, но в скриптах важно не задумыватся о работе внутри дерева интерпретатора, а их удобность. Так вот, поиск и правка хардкорного regex-а внутри скрипта у вас займёт кучу времени по сравнению со сколько комп затратит на цикл.
Хотя. если действительно считать миллисекунды, то да, надо формировать аргументы (-a -name ".$ext")* для ровно одного вызова find. Можно было б вам защитать 1:1, но вызов несколько find-ов это на много затратнее чем дерево bash-а и потому объяснение правильно лишь случайно :))) А скрипт становится развесистым и трудным для понимания.
но забудет кавычки или поставит не те и будет удивляться
Последнее исправление: vodz 14.09.17 14:16:48 (всего исправлений: 2)А я понял, вы не о внутренностях интерпретатора. Проход по файловой системе действительно долог. Разве что надеяться, что система обычно тут не очень тупит и в кеш попадает всё на первом проходе, так как файлы сами не читаются и память уходит только на сами каталоги. Признаю, думал о людях обычно глубже и сразу бросился отвечать. Но даже первый абзац остаётся в силе насчёт неудобств харкоженного и неудобного regex.
Проход по файловой системе действительно долог
Да ещё как. Если это зрелая файлопомойка на терабайт, то огого как долго можно по ней блуждать. А если оно по сети смонтировано, то всё ещё хуже. А если поиск идёт не по имени, а, например, по дате, то это вызов stat() на каждый файл.
Хотя на моём хомяке кеширование здорово помогает и разница не настолько велика, как я ожидал.
Трудночитаемость регэкспов признаю и вообще хотел бы, чтобы у find была опция -names-from-file (так-же, как grep --file=). скостылить для финда чтение паттернов из файла можно, но выглядит это ужасно.
ИзучениеКаждый файл имеет определенное расширение. Если мы хотим удалить файлы с одинаковыми или разными расширениями из нашей системы Linux, мы должны выполнять множество различных типов команд. В этой статье мы увидим, как удалить все файлы с расширением командной строки Linux.
Удалить все файлы с расширением командной строки Linux
В этом разделе будут объяснены различные способы и методы удаления всех файлов с расширениями с помощью командной строки в Linux.
Использование команды rm
В соответствующей команде «имя_файла1», «имя_файла2» и т.д. Обращайтесь к именам плюс их полные пути. Когда файлы находятся в одном каталоге, нам не нужно записывать полный путь, но мы должны указать полный путь, если это не так.
Мы можем использовать выражения с подстановочными знаками, чтобы указать инкрементные файлы с одинаковыми именами или файлы с определенными расширениями файлов. Итак, давайте рассмотрим пример, в котором мы удалим файлы DATA.txt, DATA1.txt и DATA2.txt. Эти файлы доступны в каталоге Documents, поэтому сначала мы откроем их в терминале с помощью следующей команды:
После этого выполните следующую команду
Теперь давайте проверим, что система успешно удалила файлы, поэтому выполните следующую команду/
Использование подстроки для удаления файлов
С помощью следующей команды мы можем удалить те файлы, которые содержат подстроку test.
Здесь «*» обозначает любую строку. Поэтому здесь «* test *» учитываются все файлы, имена которых имеют подстроку «test».
Мы можем легко удалить файлы с определенными расширениями из любой папки. В этом примере мы удалим файлы с расширением gif. Мы можем удалить все файлы GIF из папки, используя следующую команду.
Приведенный выше синтаксис работает только для файлов. Наряду с файлами мы также можем удалять папки с помощью аргумента ’-r’:
Главное отметить, что он удаляет папку в целом рекурсивно, то есть все файлы, подпапки и т.д. Этой папки во всей структуре папок. Это означает, что нет способа рекурсивно удалять файлы с определенными расширениями или файлы с шаблонами имен файлов.
Найти команду
Найти — самая эффективная и популярная команда для поиска файлов. Команда find используется для удаления расширений файлов в Linux. Команда find выполняет рекурсивный поиск файлов по размеру, расширению, имени и параметрам файла. Используя команду find, мы можем передать его вывод по конвейеру в ’rm’.
Резервное копирование и проверка файлов
Также используются различные команды, чтобы проверить, какие файлы мы удаляем, и их расположение правильное. Однако этот шаг необязателен, если необходимо убедиться.
Проверить местоположение
Мы должны убедиться, что расположение нашего файла правильное. Для этого мы используем следующую команду.
Резервные файлы
Для резервного копирования мы используем команду tar. Если мы не на 100% уверены, что у нас есть нужные файлы для удаления или нет, мы должны сделать резервную копию.
Мы можем добавить опцию -v, чтобы увидеть список файлов, резервные копии которых выполняет команда tar.
Удалить файлы с помощью find — удалить
Если мы не решаемся использовать rm, мы можем использовать find отдельно от этого. Его следует использовать с осторожностью. Это примерно так.
Прежде всего, мы убеждаемся, какой файл нам нужно удалить. Для этого мы используем следующую команду.
Мы должны позаботиться о том, чтобы -delete был последним аргументом в нашей команде. Если по ошибке мы поместим его перед аргументом -name *.bak, он удалит все.
Удалите файлы с помощью find и xargs
Он не поддерживает опцию «-delete». Мы можем передать его в ’rm’ следующим образом с выводом, который появляется перед нами при поиске.
Здесь мы передаем аргумент в rm с помощью команды xargs. Мы можем рекурсивно удалить всю структуру папок с помощью этого метода.
Удаляет файлы с помощью find-exec
Мы используем rm с различными командами (такими как корзина) или дополнительными параметрами для удаления файлов.
Использование find с -exec дает нам преимущество использования любых параметров и команд для удаления файлов. В то же время он также позволяет нам выполнять другие массовые операции с набором файлов.
Заключение
В этой статье мы научились удалять любой файл из папок или папок с любым конкретным расширением с помощью различных команд. Мы надеемся, что из этой статьи, объясненной нами, вы получите полную информацию в одном месте и, должно быть, очень хорошо ее поняли.
Добавить в избранноеГлавное меню » Linux » Как удалить файл в bash
Л юбой файл можно удалить временно и навсегда в bash. Когда файл временно удаляется с помощью графического пользовательского интерфейса, он сохраняется в папке «Trash» и при необходимости может быть восстановлен. Файл, который был удален безвозвратно, не может быть восстановлен позже обычным образом. Команда rm используется для окончательного удаления файла с компьютера. Если какой-либо файл был случайно удален этой командой, его можно восстановить из резервной копии. В этой статье показано, как удалить любой файл из терминала и графический интерфейс пользователя.Удаление файла с помощью команды `rm`:
Команда rm может использоваться с опцией и без опции для различных типов удаления. Синтаксис команды rm приведен ниже.
Синтаксис:
Пример-1: Удаление файла с помощью команды `rm` без опции
Пример-2: Удалите файл с помощью команды `rm` с параметром -i
Следующий сценарий запросит разрешение у пользователя перед удалением файла для параметра «-i». Здесь имя файла будет взято у пользователя в качестве ввода. Если файл существует и пользователь нажимает «n», то файл не будет удален, иначе файл будет удален.
Пример-3: Удалите файл с помощью команды `rm` с параметром -v
Пример-4: Удалить несколько файлов с помощью команды `rm`
Заключение:
В приведенных выше примерах показаны различные типы способов удаления файла с помощью сценария bash, чтобы помочь пользователям bash легко выполнять этот тип задачи.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Читайте также: