Чому mkdir не працює (у такому файлі чи каталозі немає) у сценарії з BIN_DIR = "~ / bin /"?


10

Чому команда mkdir не працює із: "Немає такого файлу чи каталогу"?

#!/bin/bash

set -e

BIN_DIR="~/bin/"

if [ ! -d "$BIN_DIR" ]; then
  mkdir "$BIN_DIR"
fi

Відповіді:


11

Повідомлення про помилку виробляється тому, що ~цитується тильда , як описано у відповіді Занні . Якщо ви хочете скористатись ~,, відповідною частиною сценарію має бути:

BIN_DIR=~/bin/

Якщо з будь-якої причини ви хочете цитувати рядок, ви можете використовувати змінну середовища $HOME:

BIN_DIR="$HOME/bin/"

На мою думку, другий підхід - це краща практика.


6
Немає нічого поганого в використанні ~в сценаріях. він працює точно так само, як і в командному рядку. Проблема полягає в тому, що цитування блоків розширення тильди, як пояснено у відповіді Занні .
тердон

@terdon, я згоден. Але я не сказав, що щось не так, але це краща ідея, тому що вам слід приділяти менше уваги.
pa4080

5
Але між командним рядком та сценарієм тут абсолютно немає різниці. Те, що це в сценарії, абсолютно не має значення, ви мали б точно таку ж помилку в командному рядку. Проблема в цитуванні, а не в тому, що це в сценарії.
тердон

Хоча це абсолютно вірно, це також правильно, що використання $HOMEв сценаріях є хорошою ідеєю.
десерт

3
@ pa4080 Чи можете ви додати пояснення, чому ви вважаєте, що краще розширити, $HOMEніж використовувати розширення tilde? Єдине пояснення, яке ви дали, - сказати, «це краща ідея, тому що вам слід приділяти менше уваги». Я поняття не маю, що це означає. Чи можете ви пояснити його в редагуванні? Без нього нічого не підтверджує вашу відповідь, так що, безумовно, вона належить до неї. Розширення Tilde вимагає POSIX вже досить довгий час, і лінія хешбангу сценарію є #!/bin/bashтаким чином, я вважаю, що портативність не є причиною.
Елія Каган

23

Це не працює, бо ~котирується. Подвійні котирування " пригнічують розширення тильди . Немає каталогу з буквальною назвою ~/bin. Як пояснено в man bash(моє наголос):

Тильда розширення

Якщо слово починається з котируваного символу тильди (`~ '), всі символи, що передують першому косого косого косу (або всі символи, якщо немає косого косого косу), вважаються префіксом тильди. Якщо жоден із символів префікса тильди не цитується, символи в префіксі тильди після тильди трактуються як можливе ім’я для входу. Якщо це ім'я для входу є нульовим рядком, тильда заміняється значенням параметра оболонки HOME. Якщо HOME не встановлено, замість цього заміняється домашня директорія користувача, що виконує оболонку. В іншому випадку префікс тильди замінюється на домашній каталог, пов'язаний із вказаним іменем входу.

Ви можете видалити лапки , оскільки ~це єдиний символ на шляху, ~/binякий змусить оболонку виконати розширення, і ми хочемо розширення в цьому випадку. Оболонки не виконуватимуть якісь - які додаткові розкладання на результаті тильди, принаймні , в Bash 4 , який все поточні або віддалено останні версії Ubuntu є . Тож навіть якщо ваш домашній каталог містить незвичайні символи, такі як пробіли, це добре.

Або ви можете використовувати $HOMEзамість цього ~, оскільки розширення параметрів не придушується подвійними лапками, а лише одинарними лапками . Подвійні лапки дійсно переконайтеся , що розширене значення не саме по собі з урахуванням будь-яких подальших розширень, тому розбиття слів або розширення файлу не відбудеться. Так $HOMEпрацює навіть із дивно названими домашніми каталогами, якщо ви дотримуєтесь подвійних лапок.


Згідно з цим твердженням, "розширення параметра не придушується подвійними лапками, а лише одинарними лапками" : вихід cd '~'є -bash: cd: ~: No such file or directory.
pa4080

2
@ pa4080 Розширення ~не є частиною розширення параметрів.
Вармар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.