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:
- 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.