Can move but cannot remove from shell script

Can move but cannot remove from shell script

I am glad I found this workaround, but maybe someone can explain this to me. I became so frustrated with it that I even explicitly spelled out the pathname each time.

I cannot remove files with a command run from a shell script which works fine if run directly in the CLI … For … security reasons? … Maybe? I don't know. There's no error message either – it seems like a success. But nothing happens.

#!/bin/bash

sudo chown -R $USER:$USER "/home/user/project/uploads"
sudo chmod -R 777 "/home/user/project/uploads" 

sudo rm -rf "/home/user/project/uploads/media/*"    # ‹———

But if I do the same with moving it works fine ¿!?¡

#!/bin/bash

DIR="/home/user/project/tmp/media"
if [ ! -d "$DIR" ]; then
    mkdir "$DIR"
fi

sudo mv "/home/user/project/uploads/media" "/home/user/project/uploads/delete-me-manually"
sudo mv "/home/user/project/tmp/media" "/home/user/project/uploads/media"

Where's the sense in that? Why is remove not working in the first place? The file permissions are correct [1] and the paths don't contain spaces or other characters. What else could be the issue?

Would be nice if my script wouldn't leave behind trash that I have to manually delete.


File permissions and ownership of script are:

-rwxr--r-- 1 user user  26K Nov 19 16:23 my-script.sh

Shell matches file shebang:

echo $0
bash 

Script is called such (not prefaced with bash or sh):

$ ./my-script.sh

File permissions and ownerships of dir are:

drwxr-xr-x 8 user user 4,0K Jul 22 21:02 /home/user/project/
drwx------ 8 user user 4,0K Nov 19 10:44 /home/user/project/tmp/

# At start of script
drwxr-xr-x 9 www-data www-data 36K Nov 19 16:35 /home/user/project/uploads/
drwxr-xr-x 65 www-data www-data 4,0K Nov 19 11:11 /home/user/project/uploads/media/

# After changing it.
drwxrwxrwx 9 user user 36K Nov 19 16:35 /home/user/project/uploads/
drwxrwxrwx 65 user user 4,0K Nov 19 11:11 /home/user/project/uploads/media/

CLI user and script user are identical (as tested with whoami).

答案1

You're not doing the same thing with mv as with rm. Look at the path arguments you give to them:

rm -rf "/home/user/project/uploads/media/*"
mv     "/home/user/project/uploads/media"   ...

"/home/user/project/uploads/media/*" is quoted, so the * is not special, and will be passed to rm as is. It goes on to remove a file literally called /home/user/project/uploads/media/*. There probably isn't one. You don't get an error message because you used the -f flag, which tells rm to "Ignore nonexistent files and missing operands, and never prompt the user." (as the GNU manual puts it).

The POSIX spec is even more explicit about -f inhibiting any error or warning messages:

For each file the following steps shall be taken:

  1. If the file does not exist:
    a. If the -f option is not specified, rm shall write a diagnostic message to standard error.
    b. Go on to any remaining files.

If you didn't use -f, it would say something like:

rm: cannot remove '/home/user/project/uploads/media/*': No such file or directory

Or, if you did the same with mv, as in mv "/home/user/project/uploads/media/*" ..., it would complain, even with mv -f.

Even unquoted, /home/user/project/uploads/media/*, isn't the same as /home/user/project/uploads/media. The other expands to a list of all files in directory (except dotfiles, usually), while the other names the directory itself. Apart from dotfiles, there's the difference that rm -r .../media/* would leave the directory media itself, while rm -r .../media would remove it, too.

You didn't show how you did run it interactively, but I'm betting you didn't quote the glob there.

相关内容