`[!]` (Восклицательный знак в скобках) подстановочный знак в bash

я встречал шаблоны подстановки и подстановочные знаки, и особый интерес для меня представляет [!] .

Эта конструкция похожа на конструкцию [!] , за исключением того, что вместо сопоставления символов внутри скобок она будет соответствовать любому символу, если он не указан между [ и ] .

rm myfile [!192]

Я полагаю, что приведенное выше приведет к удалению любых / всех файлов, за исключением любых / всех файлов, в имени которых содержится 192.

Однако меня беспокоит правильное использование этого с расширением файла и, в частности, несколько условий.

Каким будет правильный синтаксис в такой ситуации?

rm myfile [!.gif .csv. mp3] 

или

rm myfile [!.gif !.csv !.mp3]

Меня беспокоит, что точка может быть неуместна, и поэтому любой файл с . (который наверняка будет любым из них?) Будет подвергнут манипуляциям, когда я попытаюсь вызвать манипуляции с определенными файлами.

Эта конструкция похожа на конструкцию [] , за исключением того, что вместо сопоставления символов внутри скобок она будет соответствовать любому символу, если он не указан между [ и ] .

(цитата из http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm )

Сейчас; для меня это наводит на мысль о единственном числе ! достаточно, и все значения в нем находятся в пределах диапазона.

10
задан 10 November 2017 в 16:33

3 ответа

Цитирование man 7 glob:

An  expression  "[!...]"  matches  a single character, namely any character
that is not matched by the expression obtained by removing the first '!' from it.
(Thus, "[!]a-]" matches any single character except ']', 'a' and '-'.)

Акцент на односимвольную часть здесь, [] не может использоваться для целых строк в Сопоставлении с образцом Bash.


bashРасширение Фигурной скобки может привыкнуть к строкам совпадения, однако нет никакого пути (я знаю о) инвертировать их. Например.

1.{gif,csv,mp3}

расширен до

1.gif 1.csv 1.mp3

неважно, ли эти файлы существуют.


Как wchargin указанный shopt может использоваться для включения расширенных операторов сопоставления с образцом, одного из них быть !(). После выполнения shopt -s extglob, например.

1.!(gif|csv|mp3)

расширен до

1.jpg 1.bmp 1.png

если те файлы существуют в текущем каталоге. Для более чтения man bash (раздел EXPANSION/Pathname Expansion) и расширение Пути (globbing).


Поскольку, что Вы пытаетесь сделать, я всегда использовал бы find, который предлагает отрицание и намного больше, например, следующим образом:

find . -maxdepth 1 -type f ! -name "*.gif" -a ! -name "*.csv" -a ! -name "*.mp3"

Это просто перечисляет результаты, если Вы хотите удалить их, просто добавляют -delete опция в конец команды. Как всегда с удалением действий: Всегда проверяйте тщательно сначала.

find предлагает тонну полезных опций, очень хорошо объясненных man find.

16
ответ дан 23 November 2019 в 04:17

Я думаю, что Вы неправильно поняли использование скобок. [abc] соответствия один из символов a, b или c. [!abc] соответствия один символ, который не является a, b или c. Так команда

rm myfile [192]

удалит myfile и файлы 1, 9 и 2 потому что у Вас есть пространство между myfile и скобкой. Напротив, команда

rm myfile[192]

удалит файлы myfile1, myfile9 и myfile2.

10
ответ дан 23 November 2019 в 04:17

Скобки [ ] обозначьте класс символов. Любой отдельный символ в них может соответствовать в данном положении. Так

file[192]

соответствия три возможных имени:

file1
file2
file9

Это не соответствует file192, потому что это только имеет дело с отдельным символом после file.

Мы можем также использовать диапазоны в скобках. [0-9] соответствия любая единственная цифра в данном положении. Для двух цифр нам нужно [0-9][0-9]. Для цифры, сопровождаемой прописной буквой, мы могли использовать [0-9][A-Z]...

! указывает на отрицание.

file[!192]

будет соответствовать файлам, которые имеют любой отдельный символ после file кроме 1 или 9 или 2. Например, это будет соответствовать file7 и files и file% (и многие другие), но нет file192, потому что это имеет два дополнительных символа.

Для Вашего варианта использования я предлагаю использовать find вместо [!]. Это имеет a not оператор.

Это также рекурсивно, что означает, что это входит во все подкаталоги по умолчанию. Можно ограничить его текущим каталогом с -maxdepth 1, если это - то, что Вы хотите. Подстановочные знаки Shell (globbing) нерекурсивны (хотя рекурсивный globbing с ** может быть включен).

Принятие Вас не не хочет удалять символьные ссылки, мы можем добавить -type d к отрицаемым тестам, чтобы не удалять любые каталоги. Благодаря Eliah Kagan для того предложения.

find /path -maxdepth 1 -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \)

Если Вы видите то, что Вы хотите, можно выполнить команду снова с -delete

find /path -maxdepth 1  -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \) -delete
7
ответ дан 23 November 2019 в 04:17

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

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