我在 zsh 上运行了以下命令
sudo apt-get install rhythmbox*
它产生了一个错误,当我在 bash 中运行相同的命令时,它正常工作。为什么会发生这种情况?
我怎样才能使上述命令在 zsh 上运行?
答案1
以下是具体情况
Bash 将尝试在当前工作目录中评估该模式rhythmbox*
。由于不太可能有任何文件或目录以 序列开头rhythmbox
,因此它不会扩展,但 Bash 会将其作为参数提供给apt-get
此处。
请注意,如果您有一个同名的文件,rhythmbox-test
那么它将不起作用,因为它将被扩展并将rhythmbox-test
作为参数提供apt-get
。
解决方法:转义或者引用它!
因此,为了在 Bash shell 中可靠地使用模式apt-get
,您应该始终对其进行转义。使用引号或反斜杠,例如
sudo apt-get install rhythmbox\*
或者
sudo apt-get install "rhythmbox*"
zsh 也差不多。
模式的扩展称为通配符。
演示
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.
答案2
您需要使用引号来防止 zsh 扩展“*”(您希望 apt-get 扩展 * )
sudo apt-get install "rhythmbox*"
答案3
改用^rhythmbox
(与^
)。*
通常在安装或删除包时避免。
即使你引用它所以壳不变地通过,当它出现在包含大多数/操作(包括、和)*
的包名称中时,它不会执行大多数人所期望的操作。除非您确切知道它的作用和原因,否则请避免在这些操作之后使用。通常不是您真正想要的,而这正是您似乎不想要的那些时候之一。apt
apt-get
install
remove
purge
*
*
*
做不是在此上下文中表示“任何字符”。
正确的方法是apt-get
安装所有名称的软件包开始是rhythmbox
:
sudo apt-get install ^rhythmbox
这也适用于apt install
。同样,如果您需要删除此类包,您可以^rhythmbox
在remove
或purge
操作后指定。
^rhythmbox
匹配所有包名称开始因为rhythmbox
^
是行首(或在本例中为字符串首)锚点。
*
安装或删除的软件包名称中 的问题apt
是apt-get
将其解释为正则表达式,而不是 glob. 在正则表达式中,*
表示“零个或多个前一项。”因此,当您sudo apt-get install
使用rhythmbox\*
、、或(当 shell 未扩展时)运行时,您实际上是在告诉安装名称中带有任何位置的每个包。'rhythmbox*'
"rhythmbox*"
*
rhythmbox*
apt-get
rhythmbo
- 不是
rhythmbox
,,rhythmbo
因为x
会出现任意次数——零次或多次。 - 不是在开始名称或整个名称,但任何地方以其名义。
在具体情况下这特定的包,这可能不会导致大问题,因为可能只有少数包的rhythmbo
名称中有 但不以 开头rhythmbox
。但对于名称较短的包,尤其是在使用remove
或purge
操作时,这往往是灾难性的。
主要的例外是apt list
。list
动作做解释*
并?
作为通配符字符,而不是正则表达式元字符。因此,您可以搜索对于名称rhythmbox
以此开头的包:
apt list rhythmbox\*
(或者使用'rhythmbox*'
或"rhythmbox*"
。)
但安装这样的软件包——并且不要安装比你想要的更多的软件包——你仍然需要使用:
sudo apt install ^rhythmbox
或者你也可以直接传递你需要的具体包名。使用apt list
可以帮助你找到它们。