I ran the following command on zsh
sudo apt-get install rhythmbox*
It produced an error, when I ran the same command in bash it worked. Why does this happen?
How can I make the above command work on zsh?
I ran the following command on zsh
sudo apt-get install rhythmbox*
It produced an error, when I ran the same command in bash it worked. Why does this happen?
How can I make the above command work on zsh?
Bash will try to evaluate the pattern rhythmbox*
on the current working directory. As it is very unlikely there will be any file or directory starting with the sequence of rhythmbox
, it will not expand, but Bash will provide it as an argument to apt-get
here.
Note that if you have a file there with the name rhythmbox-test
then it won't work as it will be expanded and rhythmbox-test
will be provided as the argument to apt-get
.
So, to reliably use the patters in apt-get
in a Bash shell, you should always escape it. Use quotes or the backslash, e.g.
sudo apt-get install rhythmbox\*
or
sudo apt-get install "rhythmbox*"
About the same goes for zsh.
The expansion of the pattern is called 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.
You need to use quotes to prevent zsh from expanding the '*' (you want apt-get to expand the * )
sudo apt-get install "rhythmbox*"
Use ^rhythmbox
instead (with ^
). Usually avoid *
when installing or removing packages.
Even if you quote it so the shell passes it unchanged, *
doesn't do what most people expect when it appears in a package name with most apt
/apt-get
actions, including install
, remove
, and purge
. Avoid *
in the pattern that follows these actions unless you know precisely what it does and why. Usually *
is not what you actually want and this is one of those times when it seems you do not. *
does not mean "any characters" in this context.
The proper way to tell apt-get
to install all packages whose names start with rhythmbox
is:
sudo apt-get install ^rhythmbox
This also works with apt install
. Similarly, if you needed to remove such packages, you could specify ^rhythmbox
after the remove
or purge
action.
^rhythmbox
matches all package names that start with rhythmbox
because ^
is the start-of-line (or, in this case, start-of-string) anchor.
The problem with *
in the name of a package to install or remove is that
apt
and apt-get
interpret it as a regular expression rather than a glob. In a regular expression, *
means "zero or more of the preceding item." So when you run sudo apt-get install
with rhythmbox\*
, 'rhythmbox*'
, "rhythmbox*"
, or (when the shell doesn't expand *
) rhythmbox*
, you are actually telling apt-get
to install every package with rhythmbo
anywhere in its name.
rhythmbox
, rhythmbo
, because the x
is to appear any number of times--zero or more times.In the specific case of this particular package, this will likely not cause huge problems, as there are probably few packages that have rhythmbo
in their names but don't start with rhythmbox
. But with packages whose names are shorter, especially when using the remove
or purge
actions, this is often disastrous.
The main exception to this is apt list
. The list
action does interpret *
and ?
as globbing characters rather than as regular expression metacharacters. So you can search for packages whose names start with rhythmbox
like this:
apt list rhythmbox\*
(Or with 'rhythmbox*'
or "rhythmbox*"
.)
But to install such packages--and not install more packages than you mean to--you still need to use:
sudo apt install ^rhythmbox
Or you can just pass the specific package names you need. Using apt list
can help you find them.
nullglob
orfailglob
is set. – gniourf_gniourf Jun 26 '13 at 16:33