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

Эта ошибка означает, что есть проблема с источником, возможно, они внесли изменение, которое не было протестировано или не закончено. при использовании версии из SVN вы должны быть готовы к тому, что она может быть повреждена во время разработки.

1
задан 16 February 2013 в 00:04

3 ответа

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

shopt -s extglob

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

Среди прочего, он предоставляет доступ к оператор !(), который соответствует любому шаблону, не входящему в паренс. Для вашей цели:

rm !(filename).gif

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

27
ответ дан 25 May 2018 в 01:27
  • 1
    Отличный ответ! Это специфичный для bash, поэтому он не может быть подходящим для переносных скриптов, но интерактивные задачи и даже некоторые сценарии - это лучший способ перехода. Он добавляет дополнительную сложность, что extglob должен быть включен, но ничего плохого не происходит, если он отключен (в этом случае это просто не работает). По-видимому, он включен по умолчанию, хотя у меня нет shopt -s extglob в любом из моих (или глобальных) файлов конфигурации. Если есть простое объяснение, почему оно работает для меня из коробки, вы можете добавить его к этому ответу; или я могу опубликовать новый вопрос. – Eliah Kagan 19 February 2013 в 04:34

Откройте терминал с помощью Ctrl + Alt + 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
ответ дан 25 May 2018 в 01:27

Имеется переменная 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

Итак, в вашем случае: [ ! d3]

GLOBIGNORE=filename.gif; rm *.gif

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

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

Преимущество (?!) of GLOBIGNORE заключается в том, что настройка man bash не согласована и позволяет 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, но он не будет соответствовать . или [ f20], поэтому вы не будете влиять на родительский каталог таким образом.

1
ответ дан 25 May 2018 в 01:27

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

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