Я выполнил следующую команду на zsh
sudo apt-get install rhythmbox*
Она вызвала ошибку, когда я запустил ту же команду в bash, она работала. Почему это происходит?
Как я могу заставить вышеуказанную команду работать на zsh?
Bash попытается оценить шаблон rhythmbox*
в текущем рабочем каталоге. Поскольку очень маловероятно, что какой-либо файл или каталог будет начинаться с последовательности rhythmbox
, он не будет расширяться, но Bash предоставит его в качестве аргумента apt-get
здесь.
Обратите внимание, что если у вас есть файл с именем rhythmbox-test
, он не будет работать, так как будет расширен, и rhythmbox-test
будет предоставлен в качестве аргумента для apt-get
.
Итак, чтобы надежно использовать скороговорки из apt-get
в оболочке Bash, вы всегда должны избегать его. Используйте кавычки или обратную косую черту, например
sudo apt-get install rhythmbox\*
или
sudo apt-get install "rhythmbox*"
Примерно то же самое касается Zsh.
Расширение шаблона называется globbing .
touch aa ab # creates files aa and ab
ls a* # lists both files as Bash provided ls two arguments.
ls 'a*' # No such file or directory. Bash provided literally a* to ls.
ls a\* # No such file or directory. Same as above.
Вы должны использовать кавычки, чтобы zsh не расширял '*' (вы хотите, чтобы apt-get расширил *)
sudo apt-get install "rhythmbox*"
Вместо этого используйте ^rhythmbox
(с ^
). Обычно избегайте *
при установке или удалении пакетов.
Даже если вы цитируете его , поэтому оболочка пропускает его без изменений , *
не делает то, что ожидает большинство людей, когда появляется в имени пакета с большинством apt
/ apt-get
действия, в том числе install
, remove
и purge
. Избегайте *
в схеме, которая следует за этими действиями, если вы точно не знаете, что они делают и почему. Обычно *
не то, что вы на самом деле хотите, и это один из тех случаев, когда кажется, что вы этого не хотите. *
не означает , не означает «любые символы» в этом контексте.
Правильный способ указать apt-get
установить все пакеты, имена которых начинаются с с rhythmbox
, это:
sudo apt-get install ^rhythmbox
Это также работает с apt install
. Точно так же, если вам нужно было удалить такие пакеты, вы можете указать ^rhythmbox
после действия remove
или purge
.
^rhythmbox
соответствует всем именам пакетов, которые начинаются с rhythmbox
, потому что ^
является якорем начала строки (или, в данном случае, начала строки) . [+1173]
Проблема с *
в имени пакета для установки или удаления заключается в том, что apt
и apt-get
интерпретируют его как регулярное выражение, а не как глобус . В регулярном выражении *
означает «ноль или более предыдущего элемента». Поэтому, когда вы запускаете sudo apt-get install
с rhythmbox\*
, 'rhythmbox*'
, "rhythmbox*"
или (когда оболочка не раскрывается *
) rhythmbox*
, вы на самом деле говорите apt-get
установить каждый пакет с rhythmbo
где-нибудь в его имени.
rhythmbox
, rhythmbo
, потому что x
должен появляться любое количество раз - ноль или более раз. В конкретном случае этого конкретного пакета это, вероятно, не вызовет огромных проблем, так как, вероятно, есть несколько пакетов, которые имеют rhythmbo
в своих именах, но не начинаются с [ 1140]. Но с пакетами, имена которых короче, особенно при использовании действий remove
или purge
, это часто приводит к катастрофическим последствиям .
Основным исключением является apt list
. Действие list
действительно интерпретирует *
и ?
как глобализующих символов, а не как метасимволы регулярного выражения. Таким образом, вы можете искать пакеты, имена которых начинаются с rhythmbox
, например:
apt list rhythmbox\*
(или с 'rhythmbox*'
или "rhythmbox*"
.)
Но чтобы установить таких пакетов - и не устанавливать больше пакетов, чем вы хотите - вам все равно нужно использовать:
sudo apt install ^rhythmbox
Или вы можете просто передать нужные вам имена пакетов. Использование apt list
может помочь вам найти их.