LINUX.ORG.RU

Удалить файлы с определённым расширением. Как?

 


0

1

Как удалить файлы с определённым расширением?

Что нужно: удаление файлов с определённым расширением из директории /home.

В /home может быть множество различных папок.

Файлов с разными расширениями может быть много.

Решения:

1. Удалить файлы с определённым расширением. Как? (комментарий)

2. Удалить файлы с определённым расширением. Как? (комментарий)

3. Удалить файлы с определённым расширением. Как? (комментарий)

4.

#!/bin/bash

EXTENTION=("sh" "t*")

declare -a A

n=0
for i in "${EXTENTION[@]}"; do
        [ $n -ne 0 ] && A[n++]=-o
        A[n++]=-name
        A[n++]=*.$i
done
find /home -type f -a \( "${A[@]}" \) -delete

5. Удалить файлы с определённым расширением. Как? (комментарий)

★★

куча вариантов 1) на питоне напиши, расширения в кортеж, потом с помощью endswith() проверяешь файлы 2) на баше напиши 3) тупо возьми find

find ./ -type f \( -iname \*.txt -o -iname \*.iso \)

find -iregex '.*\.\(txt\|html\|iso\)$'

garik_keghen ★★★★★ ()
Ответ на: комментарий от BitSum
find /path/to/search -iname '*.ext' -exec rm '{}' \;

-exec позволяет выполнить команду, подставив найденное имя. '{}' — найденное имя, экранированная точка с запятой — конец блока -exec.

question4 ★★★★★ ()
Ответ на: комментарий от garik_keghen

Как создать переменную для указания расширений? Иначе получится колхоз.

find ./ -type f \( -iname \*.txt -o -iname \*.iso \)
BitSum ★★ ()
Ответ на: комментарий от question4

у линуксового find есть сразу опция -delete

Avial ★★★★★ ()
Ответ на: комментарий от Avial

-exec универсальный :) А вникать в этот ман нужно очень долго.

question4 ★★★★★ ()

Файлов с разными расширениями может быть много.

Забудь про расширения. Это вендузячий подход. В линуксах просто имя файла. Если точка в начале, то некоторые утилиты считают его скрытым.

А раз имя файла, то к нему можно применять регулярки. Например rm *bak

anonymous ()
Ответ на: комментарий от BitSum
find ./ -type f -iregex '.*\.\(txt\|iso\)'

тип регулярки можно задать через -regextype, список типов получить запустив 'find -regextype help', но само их описание погребено в недрах info.

ABW ★★★★ ()
Ответ на: комментарий от BitSum

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

bash таки умеет массивы.

slamd64 ★★★★★ ()
Ответ на: комментарий от ABW

Если позанудствовать, то ТСа можно понять так, что каталоги с именами типа a.txt/ удалять наверное не надо. :)

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Если позанудствовать ... каталоги с именами типа a.txt/ удалять наверное не надо

... -type f ...
Так видно лучше? Никто и не собирался ^)

bormant ★★★★★ ()
Ответ на: комментарий от bormant

Так видно лучше?

А, точно, спать надо больше :( Как же так... Наверное прокоментировать хотел пример выше, а взял последнее...

vodz ★★★★★ ()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от ozz_is_here

1) нерекурсивный
2) на большом количестве файлов тянет на переполнение комстроки

bormant ★★★★★ ()

Такой вариант ещё предложили, ну очень удобный.

unset notfirst; list='exe com bat' find /home \( $(for var in $list; do echo -n ${notfirst+" -o "} ; echo -n \ -iname  \"\*.$var\"; notfirst=1 ;done ) \) -delete
BitSum ★★ ()
Ответ на: комментарий от BitSum

Такой вариант ещё предложили, ну очень удобный.

Это небезопасное извращение. Если подствить в list «расширения» тоже в виде масок, то вместо передачи для поиска этих масок будут искаться файлы с именами удовлетворяющие этой маске:

list='t* com bat'; for var in $list ; do  echo "$var"; done

Может выдать типа:

t.c и так далее.

vodz ★★★★★ ()
Последнее исправление: vodz (всего исправлений: 3)
Ответ на: комментарий от question4
find /home -name '*.ext1' -o -name '*.ext2' -o -name '*.ext3' -type f -delete
beastie ★★★★★ ()
Ответ на: комментарий от BitSum

колхоз, но с утра голова лучше не придумала)

#!/usr/bin/env	bash

EXTENTION=("exe" "msi" "txt")


for i in ${EXTENTION[@]}; do
	find ./ -type f -name "*.${i}" 2> /dev/null
done
garik_keghen ★★★★★ ()
Ответ на: комментарий от garik_keghen

колхоз, но с утра голова лучше не придумала)

У вас таже самая ошибка. Уж сколько раз твердили миру, что есть специально придуманный синтаксис «${VAR[@]}», с кавычками, прямо отдельной строкой в документации.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

эм, давно не баше не писал, пардноньте, а то, что я поставил точку перед расширением не поможет?

"*.${i}"
. прогнал у себя по хомяку, нет ни одного ошибочного совпадения.

garik_keghen ★★★★★ ()
Ответ на: комментарий от garik_keghen

что я поставил точку перед расширением не поможет?

Нет, потому что маска развернется ещё в for i in *?[xyz]* <-- вот тут.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Так в итоге, какое конечное решение будет на баше? Чтобы я протестировал и обновил первый пост.

BitSum ★★ ()
Последнее исправление: BitSum (всего исправлений: 1)
Ответ на: комментарий от BitSum

Так вроде же понятно объяснил, надо записать «${EXTENTION[@]}» в двойных кавычках. Ну для топика там надо удалять дописать.

vodz ★★★★★ ()
Последнее исправление: vodz (всего исправлений: 3)
Ответ на: комментарий от BitSum

Это лучшее: Удалить файлы с определённым расширением. Как? (комментарий)

С переменными и, особенно, массивами в bash лучше не связывайся, с ними всегда больше ошибок и тормозов, типичный пример тут Удалить файлы с определённым расширением. Как? (комментарий)

legolegs ★★★★★ ()
Ответ на: комментарий от legolegs

С переменными и, особенно, массивами в bash лучше не связывайся

Смешно. Просто эталонно-гранитное «неасилил».

vodz ★★★★★ ()
Ответ на: комментарий от vodz

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

legolegs ★★★★★ ()
Ответ на: комментарий от legolegs

Я осилил

Увы, это не так.

во-первых, оно того не стоит и почти везде лучше

Это просто бла-бла. Чтобы не выглядеть так как и вы голословным, то «всегда» на самом деле означает «там, где нет bash», что мало похоже на топик с таким тегом.

заменять на пайпы, xargs

И этот поц говорит о тормозах и пробелах в именах...

vodz ★★★★★ ()

Обновил первый пост. Добавил скрипт на баше.

Пожалуй его и буду использовать. Наиболее компактный вариант для меня, с учётом того, что выражений десятки.

BitSum ★★ ()
Последнее исправление: BitSum (всего исправлений: 2)
Ответ на: комментарий от vodz

Увы, это не так.

Пук в лужу.

Чтобы не выглядеть так как и вы голословным,

Вариант с итерацией по башевскому массиву проходит дерево столько раз, сколько ищется расширений - это может быть и 10 и 20 раз. Многократное замедление прохода по диску - это не голые слова, а суровая реальность. А через год ТС захочет решить те-же задачу тем-же способом, но забудет кавычки или поставит не те и будет удивляться, почему простой скрипт глючит.

legolegs ★★★★★ ()
Ответ на: комментарий от legolegs

Вариант с итерацией по башевскому массиву проходит дерево столько раз, сколько ищется расширений - это может быть и 10 и 20 раз.

Это вроде бы правильно, но в скриптах важно не задумыватся о работе внутри дерева интерпретатора, а их удобность. Так вот, поиск и правка хардкорного regex-а внутри скрипта у вас займёт кучу времени по сравнению со сколько комп затратит на цикл.

Хотя... если действительно считать миллисекунды, то да, надо формировать аргументы (-a -name ".$ext")* для ровно одного вызова find. Можно было б вам защитать 1:1, но вызов несколько find-ов это на много затратнее чем дерево bash-а и потому объяснение правильно лишь случайно :))) А скрипт становится развесистым и трудным для понимания.

но забудет кавычки или поставит не те и будет удивляться

Ну на это я уже отвечал, это эталонное «ниасилил.»

vodz ★★★★★ ()
Последнее исправление: vodz (всего исправлений: 2)
Ответ на: комментарий от vodz

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

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Проход по файловой системе действительно долог

Да ещё как. Если это зрелая файлопомойка на терабайт, то огого как долго можно по ней блуждать. А если оно по сети смонтировано, то всё ещё хуже. А если поиск идёт не по имени, а, например, по дате, то это вызов stat() на каждый файл.

Хотя на моём хомяке кеширование здорово помогает и разница не настолько велика, как я ожидал.

Трудночитаемость регэкспов признаю и вообще хотел бы, чтобы у find была опция -names-from-file (так-же, как grep --file=). скостылить для финда чтение паттернов из файла можно, но выглядит это ужасно.

legolegs ★★★★★ ()
Последнее исправление: legolegs (всего исправлений: 2)
Ответ на: комментарий от legolegs

Трудночитаемость регэкспов признаю

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

Короче, вот что получилось:

#!/bin/bash

EXTENTION=("sh" "t*")

declare -a A

n=0
for i in "${EXTENTION[@]}"; do
        [ $n -ne 0 ] && A[n++]=-o
        A[n++]=-name
        A[n++]=*.$i
done
find . -type f -a \( "${A[@]}" \) -delete
vodz ★★★★★ ()
Ответ на: комментарий от vodz

Спасибо.

Заменил скрипт в первом посте на Ваше решение

BitSum ★★ ()
Ответ на: комментарий от vodz

Уточню один момент. Как я понял, то достаточно так:

EXTENTION=("dll" "exe" "iso" "so") 

и тд. Верно?

BitSum ★★ ()
Последнее исправление: BitSum (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.