Why can’t the wildcard expression be used as a non-root user

bashshellwildcards

I am using a wildcard expression to match a filename.

This is what happens with a normal, non-root user:

debian@MiWiFi-R3-srv:~$ sudo ls  /var/log/apache2/*[0-9].gz
ls: cannot access '/var/log/apache2/*[0-9].gz': No such file or directory

And this is what happens after I switch to the root user with sudo su and try the same command:

root@MiWiFi-R3-srv:/home/debian# ls  /var/log/apache2/*[0-9].gz
/var/log/apache2/access.log.10.gz  /var/log/apache2/error.log.10.gz
/var/log/apache2/access.log.11.gz  /var/log/apache2/error.log.11.gz
/var/log/apache2/access.log.12.gz  /var/log/apache2/error.log.12.gz

Why can this wildcard expression be used as root, but not as a normal, non-root user?

Best Answer

In /var/log/apache2/*[0-9].gz the substring *[0-9] is handled by the pathname expansion mechanism of the shell. Not of sudo nor ls. Of the shell. This happens before sudo or ls even starts.

To expand /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 sudo nor 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.)

Related Question