Why can't the wildcard expression be used as a non-root user?
/var/log/apache2/*[0-9].gz the substring
*[0-9] is handled by the pathname expansion mechanism of the shell. Not of
ls. Of the shell. This happens before
ls even starts.
/var/log/apache2/*[0-9].gz the shell needs to examine the content of
/var/log/apache2/. In my Debian 10 the permissions are
rwxr-x---, the ownership is
root:adm. In effect the root's shell can examine the content but a regular user's shell cannot.
Therefore the pattern gets expanded for root, but it stays verbatim for a regular user. Neither
ls expand the pattern and eventually the regular user's (elevated)
ls tries to list information about
/var/log/apache2/*[0-9].gz exactly; there is no such file or directory.
This should work for a regular user:
sudo sh -c 'ls /var/log/apache2/*[0-9].gz'
In this case
sudo will run elevated
sh and this shell will successfully expand the pattern.
(At first I thought
sudo -s … would do it, but no.)
Unlike Windows/DOS, globs are expanded by the shell before running the command in Unix systems. The shell in this case is running with your UID, not root, so it can't read that directory.
The default behaviour in the no-match case is to pass on the glob expression literally. e.g. if you run
ls xyz*xyz in your normal shell, you'll see
ls: cannot access 'xyz*xyz': No such file or directory from
ls, because it got that string as an argument.
Just like if you'd run
ls '*' to pass
* as a literal string to
ls. (Quote-removal is also the shell's job, so a command can't tell whether its arg was quoted or not.)
You can change this behaviour in bash, e.g.
shopt -s failglob means the same
ls xyz*xyz command will give
bash: no match: xyz*xyz without invoking
ls at all. (If you'd used
sudo, you would have noticed that it didn't prompt you for a password before getting this error message.)
failglob produces the same "no match" error when trying to read a directory that you don't have read permission on, unfortunately not warning you about the EPERM error that bash go when it made an
open system-call on the directory.
bash: no match: /var/log/private/*
shopt -s nullglob, where a non-matching glob expression is removed instead of passed on literally. Then your
sudo ls /...* command would have confusingly just run as
sudo ls. This is perhaps useful for scripting where you might want to do
*.gz *.tgz *.tar or something, and not get errors from the failed expansion. Probably not something you'd usually want for interactive use.)
You can use
shopt -u failglob or whatever to unset these options in a shell, if you set them to try them out.