Розширення діаграми Bash після нахилу контуру


12

Я намагаюся скопіювати файл з іншим іменем у той самий каталог, використовуючи розширення дужок. Я використовую bash 4.4.18.

Ось що я зробив:

cp ~/some/dir/{my-file-to-rename.bin, new-name-of-file.bin}

але я отримую цю помилку:

cp: cannot stat '/home/xyz/some/dir/{my-file-to-rename.bin,': No such file or directory

Навіть просте розширення дужок, як це, дає мені таку ж помилку:

cp {my-file-to-rename.bin, new-name-of-file.bin}

Що я роблю неправильно?

Відповіді:


29

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

Видаліть пробіл, і він спрацює:

cp ~/some/dir/{my-file-to-rename.bin,new-name-of-file.bin}

Незважаючи на те, що це зовсім не потрібно, зауважте, що ви можете перемістити кінцевий .binза межами дужок:

cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin

Якщо ви хочете перевірити ефект розширення дужок, ви можете використовувати це echoчи printf '%s ', printfбудь-який формат, який ви бажаєте, зробити це. (Особисто я просто використовую echoдля цього, коли я перебуваю в Bash, тому що echoвбудований Bash не розширює послідовності евакуації за замовчуванням, і тому досить добре підходить для перевірки того, яка команда насправді буде виконуватися.) Наприклад:

ek@Io:~$ echo cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin
cp /home/ek/some/dir/my-file-to-rename.bin /home/ek/some/dir/new-name-of-file.bin

23

string{foo, bar}не розширення дужок; це два слова string{foo,і bar}. Щоб використовувати розширення дужок, дужки повинні бути в одному слові. Вам доведеться або видалити зайвий простір, якщо він вам не потрібен, або процитувати його, якщо він вам потрібен:

$ printf "%s\n" aa{bb, cc}
aa{bb,
cc}
$ printf "%s\n" aa{bb,cc}
aabb
aacc
$ printf "%s\n" aa{bb," cc"}
aabb
aa cc

+1 за зрозумілий приклад, і дякую. Я дам свою підсумку, коли моя репутація буде достатньою. :)
nanangarsyad

Є щось інше, що слід згадати про "слова оболонки". . .like як оболонка знає, куди ділити слова;)
Сергій Колодяжний

-1

Баш трактує цей простір так, як і будь-який інший. Як IFS, роздільник внутрішнього поля. Це використовується для розбиття слів після розширення та для розбиття рядків на слова за допомогою команди прочитаного вбудованого.

Оболонка розглядає кожен символ IFS як роздільник, а результати інших розширень розбиває на слова з цими символами. Якщо IFS не встановлено, або його значення точно вказане за замовчуванням, то послідовності, і на початку та в кінці результатів попередніх розширень ігноруються, і будь-яка послідовність символів IFS не на початку чи в кінці служить для розмежування слова. Якщо IFS має значення, відмінне від типового, тоді послідовності пробілів та вкладок символів пробілу ігноруються на початку та в кінці слова, доки символ пробілу знаходиться у значенні IFS (символ пробілу IFS). Будь-який символ у IFS, який не є пробілом IFS, поряд із будь-якими суміжними символами пробілу IFS, обмежує поле. Послідовність символів пробілу IFS також розглядається як роздільник. Якщо значення IFS є нульовим,
-баш (1)

Вставивши роздільник, не накреслений, ви сказали, що ваша команда та аргументи bash:

  1. "cp"
  2. "~ / some / dir / {my-file-to-rename.bin,"
  3. "new-name-of-file.bin}"

Якби у вас були котирування або втеча "\", ви мали б:

  1. "cp"
  2. "~ / some / dir / {my-file-to-rename.bin, \ new-name-of-file.bin}"

Що також не було б тим, що ви хотіли, якщо тільки "new-name-of-file.bin" це нове ім'я файлу, яке ви хотіли. Місце включено. Коли розгортання дужки відбувається спочатку, а потім розширення тильди, bash виконує:

  1. "cp"
  2. "/path/to/home/some/dir/my-file-to-rename.bin"
  3. "/ path / to / home / some / dir / \ new-name-of-file.bin"

Просто вилучення простору все це виправить.


5
Це в основному добре, але, здається, ви говорите, що розбиття слів відбувається cp ~/some/dir/{my-file-to-rename.bin, new-name-of-file.bin}і IFSвпливає на результат. Ні це не так. Тут простір є метахарактером в токенізації ( крок 2 ). Дивіться 3.5.7, коли відбувається розщеплення. Спробуйте IFS=xпотім printf '[%s]\n' {a,b} printf '[%s]\n' {a, b} printf '[%s]\n' {a,xb} printf '[%s]\n' {a, xb}.
Елія Каган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.