1

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

2
  • 4
    * is not expanded when in quotes. I'd treat this as a typo. Also, what's the sense in all the sudo calls?
    – Kusalananda
    Nov 19, 2020 at 15:58
  • The sudo calls there are to make sure commands run by user user can manipulate www-data files. And, because I got more and more frustrated. Nov 19, 2020 at 16:27

1 Answer 1

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.

4
  • You're right, I didn't quote the glob there. Didn't know about that asterisk thing inside quotes. Sometimes Linux is arbitrarily confusing. (The skipped error message due to the -f flag is totally on me, though) Nov 19, 2020 at 16:34
  • @WoodrowShigeru There is nothing arbitrary about the quoting rules of the shell.
    – Kusalananda
    Nov 19, 2020 at 16:58
  • Well, I mean: if you're using variables then you have to quote them because of potential spaces rm "$DIR". But now I learned to be careful not to include asterisks in the quotes. The rm man page doesn't mention anything about this asterisk trap either – probably, because it's specific to the shell and not the command. If you know about it, it's logical. If you don't, you have no idea this could possibly be an issue. Nov 19, 2020 at 17:07
  • @WoodrowShigeru, quotes stop glob characters from being special like they stop most other things from being special too. A variable could also contain globs, and quotes stop such from being expanded by surprise. Try foo=* and compare echo $foo vs. echo "$foo"
    – ilkkachu
    Nov 19, 2020 at 17:51

You must log in to answer this question.

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