расширение оболочки (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. Выражение в скобках [...]работает так же, как и в регулярном выражении, но !вместо ^слова «не в». [...]Модель всегда будет соответствовать один символ.
Кусалананда
Вы правы! Кстати, я {1,2}тоже не POSIX-совместимый ... узнал несколько новых вещей сегодня!
thecarpy
2
Тот факт, что расширения скобок не должны совпадать с реальными файлами, может быть чрезвычайно полезным, если вы используете его для (например) генерации шаблонов для передачи grep, генерации URL для передачи curlи т. Д., Но это также может сбивать с толку людям, которые привыкли работать с шариками.
Кевин
@ Кевин Верно. Расширение скобки не должно быть о именах файлов.
Кусалананда
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) файлов.

thecarpy
источник
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
Inian
источник
2
Нет, не беспокойтесь о том, что файлов там нет, я просто хотел показать, что содержимое двух файлов пронумеровано численно, но это не является последовательным, поэтому file{1,5}синтаксис запятых был всем, что я пропустил!
Джо Хили