`[!]` (восклицательный знак в скобках) подстановочный знак в 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
задан 11 November 2017 в 03:33

9 ответов

Цитирование 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 Match Matching.

bash 's man 7 glob может использоваться для сопоставления строк, однако нет способа (я знаю) отрицать их. Например,

1.{gif,csv,mp3}

разворачивается до

1.gif 1.csv 1.mp3

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

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

1.!(gif|csv|mp3)

будет расширен до

1.jpg 1.bmp 1.png

, если эти файлы существуют в текущем каталоге. Более подробно читайте wchargin (раздел EXPANSION / Расширение пути) и Расширение пути (globbing).

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

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

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

find предлагает массу полезных опций, очень хорошо объясненных Расширение Pathname (globbing) .

16
ответ дан 22 May 2018 в 16:21
  • 1
    Обратите внимание, что эта команда find рекурсивна ( edit: поскольку она была первоначально показана - я могу оставить комментарий для дополнительной релевантной, но несущественной информации, которую она передает). Чтобы найти файлы, находящиеся только в текущем каталоге, но не также его подкаталоги, и, таким образом, удалять только эти файлы, если действие -delete добавлено - вы можете добавить -maxdepth 1 сразу после find .. Это приведёт его в соответствие с эффектом globbing, поскольку globs нерекурсивны в Bash, если не включена опция globstar shell и **. Шаблон, показанный в вопросе, является нерекурсивным во всех оболочках. – Eliah Kagan 10 November 2017 в 13:59
  • 2
    «нет способа (я знаю)», чтобы отменить их »с помощью shopt -s extglob, вы можете использовать echo 1.!(gif|csv|mp3), который печатает все 1.ext, где ext не gif, csv или [ f7]. (См. Подраздел «Соответствие шаблону» man bash.) – wchargin 10 November 2017 в 17:01

Цитирование 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 Match Matching.

bash 's man 7 glob может использоваться для сопоставления строк, однако нет способа (я знаю) отрицать их. Например,

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

, если эти файлы существуют в текущем каталоге. Более подробно читайте wchargin (раздел EXPANSION / Расширение пути) и Расширение пути (globbing).

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

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

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

find предлагает массу полезных опций, очень хорошо объясненных Расширение Pathname (globbing) .

16
ответ дан 18 July 2018 в 03:32

Цитирование 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 Match Matching.

bash 's man 7 glob может использоваться для сопоставления строк, однако нет способа (я знаю) отрицать их. Например,

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

, если эти файлы существуют в текущем каталоге. Более подробно читайте wchargin (раздел EXPANSION / Расширение пути) и Расширение пути (globbing).

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

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

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

find предлагает массу полезных опций, очень хорошо объясненных Расширение Pathname (globbing) .

16
ответ дан 24 July 2018 в 17:52

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

rm myfile [192]

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

rm myfile[192]

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

10
ответ дан 22 May 2018 в 16:21
  • 1
    правда. Лучше использовать find. – RoVo 10 November 2017 в 13:14
  • 2
    Фактически [] используется для диапазона, [!] Один символ – IronUhlan 10 November 2017 в 13:14
  • 3
    @IronUhlan, они оба берут диапазон или список символов. Просто другое отрицание. – ilkkachu 10 November 2017 в 17:29

Кронштейны [ ] обозначают класс символов. Любой отдельный символ внутри них может совпадать в данной позиции. Итак,

file[192]

соответствует трем возможным именам:

file1
file2
file9

Он не соответствует file192, поскольку он имеет дело только с одиночным символом после file. [!d2 ]

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

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

file[!192]

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

я использую find вместо [!]. Он имеет оператор not.

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

Предполагая, что вы не хотите избегать удаления символических ссылок, мы можем добавить -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
ответ дан 22 May 2018 в 16:21
  • 1
    И я думаю, вы также можете сделать несколько диапазонов одновременно. Например, шестнадцатеричная цифра может быть [0-9a-fA-F] – Wilson 10 November 2017 в 15:27
  • 2
    @ Занна, да! Я действительно использовал find :) Не понял, что у него есть «нет». оператор :) – IronUhlan 10 November 2017 в 18:14

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

rm myfile [192]

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

rm myfile[192]

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

10
ответ дан 18 July 2018 в 03:32

Кронштейны [ ] обозначают класс символов. Любой отдельный символ внутри них может совпадать в данной позиции. Итак,

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 вместо [!]. Он имеет оператор not.

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

Предполагая, что вы не хотите избегать удаления символических ссылок, мы можем добавить -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
ответ дан 18 July 2018 в 03:32

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

rm myfile [192]

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

rm myfile[192]

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

10
ответ дан 24 July 2018 в 17:52
  • 1
    правда. Лучше использовать find. – RoVo 10 November 2017 в 13:14
  • 2
    Фактически [] используется для диапазона, [!] Один символ – IronUhlan 10 November 2017 в 13:14
  • 3
    @IronUhlan, они оба берут диапазон или список символов. Просто другое отрицание. – ilkkachu 10 November 2017 в 17:29

Кронштейны [ ] обозначают класс символов. Любой отдельный символ внутри них может совпадать в данной позиции. Итак,

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 вместо [!]. Он имеет оператор not.

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

Предполагая, что вы не хотите избегать удаления символических ссылок, мы можем добавить -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
ответ дан 24 July 2018 в 17:52
  • 1
    И я думаю, вы также можете сделать несколько диапазонов одновременно. Например, шестнадцатеричная цифра может быть [0-9a-fA-F] – Wilson 10 November 2017 в 15:27
  • 2
    @ Занна, да! Я действительно использовал find :) Не понял, что у него есть «нет». оператор :) – IronUhlan 10 November 2017 в 18:14

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

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