9

Who can give me a logical explanation to this issue:

I can not run this command:

sudo cp /data/*20150522* /backup/

cp: cannot stat `/data/*20150522*': No such file or directory

And when i switch to root its working with no problem.

I'm sure it is about having the right privileges to list the files inside to /data directory which have the folowing access privileges:

drwxrwx--- 1 root root 

But here i'm running the command with sudo, so what is the problem here?

6
  • 1
    Unless you are a member of the root group, it does not have permission to list the directory. You would need it to be at least 751 (drwxrwx--x) for a non-root user to list the directory.
    – Michael
    May 22, 2015 at 16:45
  • 1
    Offtopic, not a programming question.
    – Marc B
    May 22, 2015 at 16:45
  • @Michael Adding members to the root group sounds weird and is a potential security risk since root would need to be very careful when creating something in the filesystem. I would use a special group for this, like admin . Unless I chown root:admin something I don't need to take special care.
    – hek2mgl
    May 22, 2015 at 17:02
  • 1
    @hek2mgl Oh it sure does - I didn't meant to imply the user should be added, just that the current perms wouldn't work.
    – Michael
    May 22, 2015 at 17:03
  • @Michael Yes, got that. Just wanted to add this. :)
    – hek2mgl
    May 22, 2015 at 17:05

1 Answer 1

21

The shell attempts expansion of the glob pattern before it passes the expanded result to cp (actually, it is passing the result to sudo which then passes it unchanged to cp). Since the shell (it is running as you, not root) is not able to traverse the directory, cp ends up receiving the unexpanded pattern in its argument list.

cp does not perform any glob expansion itself. It expects a list of file names. The string with the pattern in it does not name a file.

Perhaps the most straight forward way to perform the task is to invoke your command in a sub-shell. Quote the command with either double quotes (") or single quotes (').

sudo sh -c "cp /data/*20150522* /backup/"
sudo sh -c 'cp /data/*20150522* /backup/'

This works because the sub-shell expands the glob pattern in the command string before invoking the command. Since the sub-shell is running as root under sudo, the expansion is successful.

Using double quotes to quote the command to the sub-shell allows the parent shell to expand shell variables before invoking the sudo command. If you want variables to be expanded by the sub-shell, the single quotes should be used instead. In this case, it is equivalent, since you do not have any variables. But, you could add one to see the difference in behavior.

sudo sh -c "echo $USER; cp /data/*20150522* /backup/"
sudo sh -c 'echo $USER; cp /data/*20150522* /backup/'

The first command will display your user name, while the second command will display the root user name.

5
  • 1
    Can this behaviour be worked around somehow? sudo <something> with wildcards expansion with raised privileges.
    – Eugene Sh.
    May 22, 2015 at 16:52
  • 1
    Maybe something like this sudo bash -c 'cp /data/*foo* /dest' instead?
    – Zoredache
    May 22, 2015 at 17:23
  • @Zoredache: I had just thought of that before reading your comment. Thanks.
    – jxh
    May 22, 2015 at 17:29
  • I think you are wrong with the " vs '. None of them will expand the *, the difference is in the expansion of shell variables (try with "$UID" and '$UID').
    – rodrigo
    May 22, 2015 at 19:29
  • @rodrigo: You are correct, I have updated the answer. I knew about the shell variable expansion, but for some reason I expected that to hold for glob expansion as well.
    – jxh
    May 22, 2015 at 21:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .