Существует множество ситуаций, когда использование a *
практически неизбежно, например, rm -rf *
в папке, содержащей тысячи вложенных папок и файлов.
Но что, если вы хотите исключить из команды только один или два файла или папки rm
? Я гуглил свой путь и нашел только довольно сложные решения, find . -depth -not \( -name 'one' -o -name 'two' \
-o -name 'three' \) -exec rm {} \;
как указано здесь .
Есть ли возможность сделать это проще - без этого обхода find
? Например, rm -rf --exclude='one' --exclude='two' --exclude='three' *
как в Rsync или просто rm -rf -e 'one','two','three' *
?
Может быть , даже вообще возможность исключить вещи из *
(так что другие команды типа cp
, mv
... не должны реализовывать свои собственные)? Что-то вроде *{'one','two','three'}
или так?
источник
find
эту--delete
опцию (не нужно выполнятьrm
для каждого файла. Это ненужные накладные расходы).mv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three
, но я бы предпочел решение, дающее возможность явно исключать что-либо из*
. Безусловно, будут ситуации, когда перемещение или копирование файлов в другое место назначения будет невозможным.Ответы:
Для Bash есть опция оболочки,
extglob
которая по умолчанию отключена, чтобы сохранить совместимость со стандартным синтаксисом оболочки. Extglob дополняет синтаксис дополнительными операторами , как!()
,?()
,@()
и некоторые другие.Чтобы включить
extglob
, введитеshopt -s extglob
. Чтобы он был включен для текущего типа пользователяecho 'shopt -s extglob' >> ~/.bashrc
.Для примера rm: С
extglob
вы можете использоватьисточник
shopt
вещь в свой~/.bashrc
, это не повредит.*
, а вместо этого добавляет аналогичные индикаторы (например,!
), которые имеют дополнительные функции? В таком случае это было бы прекрасным решением.Я построил, кроме как для этого (извините, что я еще не смог добавить документацию).
У меня есть папка, подобная следующей:
Печатание
except b d
даст вамa
иc
Теперь вы можете передать это
rm
.Это может быть трудно запомнить, так почему бы просто не создать скрипт поверх, кроме называемого
rm-except
:Точно так же легко это
ls-except
:источник
В качестве альтернативы extglob (хотя это очень хороший ответ, и каждый должен иметь
shopt -s extglob globstar
в своем .bashrc), вы можете использовать глобальную переменную $ GLOBIGNORE . Допустим, вы хотите получить все файлы, кроме «foo.txt» и «bar baz.txt»:... однако, это включит параметр оболочки
dotglob
, что означает, что*
будут совпадать файлы, начинающиеся с точки (которые обычно скрыты). Таким образом, вам на самом деле нужны две команды:Так как это глобальная переменная, она будет влиять на каждый глобус, который вы используете, до тех пор, пока $ GLOBSTAR не будет сброшен при выходе или
Он также будет работать только с литеральными строками, переданными в переменную. Вы можете понять, что я имею в виду, установив $ GLOBIGNORE и посмотрев на разницу между этими командами:
источник