Удаление файлов с определенным расширением, кроме одного файла из терминала

Мне нужно удалить все файлы с расширением .gif, кроме одного файла с именем «filename.gif». Каков оптимальный способ сделать это в терминале?

Команда rm *.gif удаляет все файлы gif, включая файл filename.gif.

36
задан 15 February 2013 в 22:04

4 ответа

Вот простое решение, которое необходимо, вероятно, использовать:

mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif

Нет ничего специального о .keep расширение, это просто делает его так, чтобы имя файла временно не заканчивалось в .gif.

Если Вы не должны переименовывать файл (и там пишут сценарий ситуаций, где это важно):

for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done

Или можно записать это короче как это:

for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done

Можно предпочесть использовать find вместо этого; это очень мощно, Вы могли бы считать это более читаемыми, и это лучшие дескрипторы странные имена файлов с символами как * в них.

find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete

Я использовал -not оператор для удобочитаемости, но если соответствие POSIX важно - если Вы не используете GNU, находит, или если это для сценария, Вы намереваетесь перераспределить другим или работать на множестве систем - необходимо использовать ! оператор вместо этого:

find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete

Одна удобная вещь о find это, можно легко изменить команду для нечувствительности к регистру, так, чтобы она нашла и удалила файлы с расширениями как .GIF также:

find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete

Обратите внимание на то, что я использовал -iname вместо -name для шаблона поиска *.gif но я не использовал его для filename.gif. По-видимому, Вы знаете точно, чем Ваш файл называют, и -iname будет соответствовать альтернативной капитализации не только в расширении, но и где угодно в имени файла.

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

Если Вы хотите удалить файлы, везде содержавшие в текущем каталоге (то есть, включая в подкаталогах, и в подкаталогах тех подкаталогов, и т.д - файлы, содержавшие в текущем каталоге или каком-либо из его потомков), использование find без maxdepth -1:

find . -not -name 'filename.gif' -name '*.gif' -delete

Будьте осторожны с этим!

Можно также установить другие значения с -maxdepth. Например, для удаления файлов в текущем каталоге и его детях и внуках, но не немного глубже:

find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete

Просто удостоверьтесь, что Вы никогда не помещаете -delete во-первых, перед другими выражениями! Вы будете видеть, что я всегда помещал -delete в конце. При помещении его вначале это было бы оценено сначала, и все файлы под . (включая файлы, не заканчивающиеся в .gif и файлы в глубоком sub-sub-sub... каталоги .) был бы удален!

Для получения дополнительной информации см. страницы руководства для bash и sh и поскольку команды использовали в этих примерах: mv, rm, [, и (особенно) find.

66
ответ дан 15 February 2013 в 22:04

Если вы используете bash (оболочка по умолчанию), опция оболочки extglob позволяет вам использовать расширенный синтаксис сопоставления с образцом. Чтобы включить его, используйте встроенную команду shopt:

shopt -s extglob

(я включаю эту строку в мой файл .bashrc.)

Помимо прочего, он предоставляет доступ к [ 116] оператор, который соответствует любому шаблону, не находящемуся внутри скобок. Для вашей цели:

rm !(filename).gif

Дополнительную информацию можно найти в man bash в разделе «Сопоставление с образцом».

0
ответ дан 15 February 2013 в 22:04

Откройте Terminal with Ctrl + Высокий звук + T и тип:

find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;

Разница между -delete и -exec rm -vf {} \; это со второй опцией, Вы сможете видеть, какие файлы были удалены, из-за -v флаг. Это - что-то, что не может быть, покончили -delete опция. (-name -delete распечатает имена файлов, но rm с -v показывает, был ли каждый файл успешно удален.)

13
ответ дан 15 February 2013 в 22:04

Это переменная GLOBIGNORE. Из man bash :

GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.

Итак, простой способ - просто установить GLOBGINORE на имя файла, о котором идет речь:

$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png

Итак, в ваш случай:

GLOBIGNORE=filename.gif; rm *.gif

Конечно, поскольку GLOBIGNORE содержит шаблоны, вы можете использовать его, когда хотите исключить шаблон:

$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png

Преимущество (? !) из GLOBIGNORE заключается в том, что установка автоматически исключает . и .. из сопоставления и позволяет dotglob:

The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.

Итак, простой способ удаления всех файлов и папок в каталоге:

GLOBIGNORE=.; rm -r *

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

0
ответ дан 15 February 2013 в 22:04

Другие вопросы по тегам:

Похожие вопросы: