Remove files from a root-owned directory using sudo with wildcards

Cause

The shell interprets and expands any glob characters (wildcards) such as the asterisk. This interpretation of the command happens in the current shell (before the sudo command is executed) which doesn’t have read permission for the directory. Since the current shell can’t find files that match the glob pattern, pathname expansion is not carried out and the shell passes rm, -f, and /var/log/nginx/ab* (with a literal asterisk) as the arguments to the sudo command.

The sudo command, in turn, launches the rm command which tries to remove a file with a path of /var/log/nginx/ab* (an asterisk is a legal character for a Unix filename). Since such a file doesn’t actually exist, it reports its failure. With GNU rm, this error message is explicit; the full error message below indicates that the (single) file being removed doesn’t exist:

rm: cannot remove `/var/log/nginx/ab*': No such file or directory

Solution

The solution is to launch a new shell as the superuser with the necessary permissions to perform the filename expansion:

sudo bash -c "rm -f /var/log/nginx/ab*"

The above command starts a new shell which is run as root and the -c option is used to pass the command to be run by the shell. Since the command is quoted, the asterisk is not interpreted by the current shell and is passed as it is to the new root shell allowing it to expand the pathnames before launching the rm command.


It's either problem with your file names or possible spaces in their file names.

So try the following workarounds:

  1. Try precede --to signify the end of the options, e.g.:

    sudo rm -vf -- /var/log/nginx/ab*
    
  2. Use find:

    sudo find /var/log/nginx -name "ab*" -print -delete
    
  3. If you think your files are protected on Linux, try removing the protection first:

    chattr -i ab*