розширення оболонки (A | B) у назви файлів?


9

Чи можливо розширити orвибір в оболонці, читаючи файл, наприклад.

Я маю на увазі під цим те, що, наприклад, grepпідтримує синтаксис, подібний (A|B)до A або B у файлі.

Аналогічно, якщо у мене є ці файли:

file1.txt
file2.txt
file3.txt
file4.txt
file5.txt

Я міг би зробити cat file{1..5}.txtв bash, як він розширює діапазон. Чи існує еквівалентний спосіб зробити це лише для декількох файлів?

Наприклад, cat file(1|5).txtі друкувати лише ці 2?

Відповіді:


16

Стандартний шаблон імені файлу підстановка , щоб відповідати цифра є [0-9]. Це відповідає одній цифрі:

cat file[0-9].txt

Щоб вибрати лише два з них:

cat file[25].txt

Для більшої кількості, ніж 9, розгортання дужок буде корисним (але див. Примітку нижче про різницю між моделями глобалізації та розширенням дужок):

cat file{25..60}.txt

Знову ж таки, розширення брекетів дозволяє і для окремих номерів:

cat file{12,45,900,xyz}.txt

(зауважте, що у наведеному вище прикладі розширення дужок не передбачає арифметичного циклу, а просто генерує назви на основі наданих рядків).

У випадку bash, якщо параметр extglobоболонки включений ( shopt -s extglob), також буде працювати наступне:

cat file@(12|45|490|foo).txt

@(...)Шаблон буде відповідати будь-який один з включених |-delimited моделей.


Різниця між шаблонами глобалізації як [...]і @(...)розширеннями брекетів полягає в тому, що розширення дужок генерується в командному рядку і фактично не може відповідати жодним існуючим іменам у поточному каталозі. Шаблон шаблону імені файлів буде відповідати іменам, але оболонка не буде скаржитися, якщо існує не все можливе ім'я. Якщо не існує відповідного імені, шаблон залишатиметься нерозкритим, якщо також не встановлено nullglobпараметр оболонки, і в такому випадку шаблон буде видалено.

Приклад:

touch file1

ls file[0-9]

Тут file1буде показано лише список файлів для .

З ls file{0..9}, lsбуде скаржитися нема знайти file0, і file2т.д.

У наступному прикладі перша команда торкнеться лише існуючих імен, що відповідають заданому шаблону, а друга лінія створить файли, які ще не існують:

touch file[0-9]

touch file{0..9}

@thecarpy Вибачте, але це не зразок, який би відповідав, наприклад file45.txt. Вираз дужки [...]працює так само, як у звичайному вираженні, але використовує !замість того, ^щоб сказати "не в". [...]Модель завжди буде відповідати один символ.
Kusalananda

Ти правий! До речі, моє {1,2}не відповідає POSIX ... сьогодні дізнався кілька нових речей!
thecarpy

2
Той факт, що розширення дужок не повинні відповідати реальним файлам, може бути надзвичайно корисним, якщо ви використовуєте його для (наприклад) генерування шаблонів для передачі grep, створення URL-адрес для передачі curlтощо ..., але це також може заплутати людям, які звикли працювати з глобусами.
Кевін

@Kevin Правильно. Розширення дужок не повинно стосуватися імен файлів.
Kusalananda

7

Синтаксис, який слід використовувати, - це те, file{1,2}що буде оцінено до file1та file2.

$ ls
$ touch file{1,2,3,4,5,6,7,8,9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

Як зазначав Ініан нижче, і touch file{1..9}в цьому прикладі було б простіше ...

$ ls
$ touch file{1..9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

Ви також можете використовувати кілька виразів, наприклад:

$ ls
$ touch file{1..9}{a..z}
$ ls
file1a file1b file1c
[...]
file9x file9y file9z

Так, вищесказане створить 234 ( 9рази 26) файли.


1
Цей file{1,2} синтаксис також зручний для перейменування файлів:mv some_very_long_filename.txt{,.bak}
Ерік Дюмініл

6

Так, ви можете використовувати розширення дужок в bashоболонці. Для декількох файлів просто так file{1..2}чи інакшеfile{1,2}

Або якщо ви переживаєте, що файли в деяких випадках відсутні, просто зробіть просту петлю,

for file in file{1..4}.txt; do
    [ -f "$file" ] || continue
    echo "$file" # Do other actions on file here
done

Або якщо просто об'єднання - це ваша єдина операція над файлами, і якщо ви не впевнені, які файли не могли бути присутніми в будь-який момент часу, просто catїх і пригнічуйте помилки. Перенаправлення стандартної помилки на /dev/nullпридушення помилок, якщо файл недоступний.

cat file{1,5}.txt 2>/dev/null

або використовувати вираз glob, file[15]який не скаржиться на помилки, якщо файл не був знайдений.

cat file[15].txt

2
Ні, жодних занепокоєнь щодо того, що файлів немає, я просто хотів показати вміст 2-х файлів, пронумерованих числовим числом, але це не є послідовним, тому file{1,5}синтаксис комами був усім, що мені не вистачало!
Джо Хелі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.