Почему «cat {foo}» не выводит foo, а «cat {foo, bar}» делает?

12

Я пытался объединить текстовые файлы в подпапках и попытался:

cat ./{mainfolder1,mainfolder2,mainfolder3}/{subfolder1}/book.txt > out$var

Однако это ничего не вернуло. Итак, попытался добавить несуществующую подпапку2

cat ./{mainfolder1,mainfolder2,mainfolder3}/{subfolder1,subfolder2}/book.txt > out$var

И на этот раз все получилось, конкатенация файлов прошла успешно. Почему это происходит?

CDPF
источник
2
Используйте echoвместо того, catчтобы увидеть, какую командную строку вы получили. (Или используйте set -xдля отладки.)
Питер Кордес

Ответы:

22

По определению, расширение скобок в GNU Bash требует либо выражения последовательности, либо серии значений, разделенных запятыми:

Шаблоны, которые должны быть развернуты в фигурные скобки, принимают форму необязательной преамбулы, за которой следует либо последовательность строк, разделенных запятыми, либо выражение последовательности между парой фигурных скобок, за которым следует необязательный postScript.

Вы можете прочитать руководство для деталей.

Несколько простых примеров:

echo {subfolder1}
{subfolder1}

echo {subfolder1,subfolder2}
subfolder1 subfolder2

echo subfolder{1}
subfolder{1}

echo subfolder{1..2}
subfolder1 subfolder2
Артур Хесс
источник
21

{subfolder1}оценивает {subfolder1}, так как нет альтернатив. Используйте subfolder1вместо этого.

Игнасио Васкес-Абрамс
источник
2
Обратите внимание, что он отличается от in csh(откуда берется расширение скобок) tcshили fish.
Стефан Шазелас
1

Скобки будут расширяться только в том случае, если у них есть строки, разделенные запятой, например, {abc, def} или диапазон, например, {a..e}, указанный между ними.

В вашем случае вы можете просто написать подпапку1, не заключая ее в фигурные скобки, так как в этом нет необходимости

cat ./{mainfolder1,mainfolder2,mainfolder3}/subfolder1/book.txt > out$var
Neo_Returns
источник
К сожалению, /path/{a,}/filenameрасширяется до двух строк /path/a/filenameи /path//filename, что может быть нежелательным.
Кусалананда
спасибо @Kusalananda за исправление, да, bash выдаст предупреждение «неоднозначное перенаправление»
Neo_Returns
Нет, вы получите, ambiguous redirect если попытаетесь перенаправить в файл, заданный переменной без кавычек, которая не имеет значения, например echo 'hello' >$idontexist.
Кусалананда
1
... или если имя файла в перенаправлении будет расширено до нескольких слов. Как > *.txtс несколькими .txtфайлами, или > $fileесли $fileсодержит пробелы. Но, конечно, нет ничего неоднозначного в приведении catмножества аргументов
ilkkachu