ls with directory path shows files, but ls with file pattern does not?

1

Why is this happening?

$ sudo ls /var/lib/postgresql/9.4/pg_log/
postgresql-2015-03-23_134626.log  postgresql-2015-03-25_000000.log  postgresql-2015-03-25_095920.log
postgresql-2015-03-24_000000.log  postgresql-2015-03-25_095626.log
$ sudo ls /var/lib/postgresql/9.4/pg_log/*
ls: cannot access /var/lib/postgresql/9.4/pg_log/*: No such file or directory

ls /path/to/dir/ shows files, but ls /path/to/dir/* says no files found.

Why is this?

Richard

Posted 2015-03-25T10:18:33.350

Reputation: 419

Answers

1

The wildcard is expanded by the shell before sudo is run. The current user can't access the files, so the string is passed literally to sudo and later ls. ls doesn't expand wildcards (it's the shell's duty), so it can't find the file named *.

Protect the wildcard by quoting and call a root shell to expand it:

sudo sh -c 'ls /var/lib/postgresql/9.4/pg_log/*'

choroba

Posted 2015-03-25T10:18:33.350

Reputation: 14 741

Will enclosing the path with * in double quotes (sudo ls "/path/to/dir/*") delay expansion to the appropriate time? – hBy2Py – 2015-03-25T10:40:30.257

@Brian: No. You need to call a shell to do the path expansion. – choroba – 2015-03-25T10:44:05.740

3

You’re experiencing an aspect of the problem discussed in sudo unable to write to /etc/profile and How to append to a file as sudo?, and the issue discussed in Who deals with the * in echo *?  Your primary shell interprets each command you type, including wildcards (also known as globs or filename patterns).  If you type

some_command *

the shell enumerates the files in the current directory and passes them to the command; e.g.,

some_command black blue brown green orange red white yellow

Well, if you don’t have permission to read /var/lib/postgresql/9.4/pg_log, then your shell doesn’t have permission to enumerate /var/lib/postgresql/9.4/pg_log/*.  The fact that, when the command runs, it runs as root, is too little, too late — pathname expansion (i.e., wildcard interpretation) is done by then.

You can fix this with a trick discussed in the first two questions I referenced:

sudo sh -c "ls /var/lib/postgresql/9.4/pg_log/*"

This runs a privileged shell.  The privileged shell can then expand the *.

Scott

Posted 2015-03-25T10:18:33.350

Reputation: 17 653