0

I have a task which contain a series of manual steps. One of the steps is to execute rm -rf *. Everything in the folder does need to be deleted but this seems a little dangerous for example. if the user is not paying attention and is in the wrong folder when they run the command.

Is there any safe way to preform the task of removing everything in the folder?

  • What sort of "safe way" are you imagining (what makes it safe)? – Michael Homer Apr 30 '19 at 07:19
  • is the -r needed. why is the -f needed? – Grump Apr 30 '19 at 07:45
  • 1
    Make 100% sure you are in the right directory. You might even want to specify explicitly: rm -rf /full/path/to/dir/* -- I must confess this bit me once: had to restore the server from tape backup. – glenn jackman Apr 30 '19 at 12:55
  • Well... always double check what you are doing... I would say it's the rule when playing in terminal. You can also add -i to your rm command to ask you for a confirmation for each file it will delete but it's a bit painful... – darxmurf Apr 30 '19 at 13:18
  • I have made rm -rf * report an error by implementing a shell function that serves as the alternative to it. The code is available at CodeReview SE if you are really interested (I bet you aren't) – Weijun Zhou Apr 30 '19 at 13:43
  • There might be an answer to this already. I would suggest adding the -i flag or creating an alias; e.g. alias rm='rm -i'. – ILMostro_7 Apr 30 '19 at 15:41

3 Answers3

4

Yes, move one step up in the directory hierarchy and do rm -rf dirname on the specific directory name (no filename globbing should be involved in that command).

This way, the user would not accidentally remove the wrong things if they happen to be in the wrong directory, unless they were unfortunate enough to have an identically named but unrelated directory in the current working directory. It would additionally remove any hidden files and directories that rm -rf * would miss (due to * not expanding to hidden names).

Then re-create the directory if you need to.

Another option would be to not delete the directory, but to rename it (and possibly archive and compress it). This would also be done from the directory's parent directory, and would allow you to later recover files from that directory. Whether this is a viable option depends on what this directory holds and what the task at hand actually is.

Also related:

Kusalananda
  • 333,661
  • Note that if you are in the directory when you run the script, then the calling shell will end up in a directory that no longer exists which may cause issues. (Recreating the directory with the same name does not prevent this.) – William Pursell Apr 30 '19 at 15:30
  • @WilliamPursell This would be an issue if the user has more than a single shell session active, yes. This is not different from removing any other directory though. – Kusalananda Apr 30 '19 at 15:36
  • rm -rf * also has a problem with file names that start with -. – Stéphane Chazelas Apr 30 '19 at 15:39
0

Easy. To delete everything in the current folder:

rm -rf ./*

./ directs to the current directory, so ./* is everything in current directory. (Just don't forget the dot, seriously, do not forget the dot)

As said in Kusalananda's answer, this does not cover hidden files (so to erase hidden files you need to do a separate rm -rf ./.*)

To get fancy (command that removes everything including hidden files, safely in one shot)

rm -rf ./{,.[!.],..?}*

But chances are that rm -rf ./* ./.* will also be safe (not sure if you wanna take that chance)

If you want to be perfectly safe and aren't sure what folder you are in, the only way is

rm -rf /path/to/folder/*

or

rm -rf /path/to/folder/{,.[!.],..?}*
Cestarian
  • 2,051
0

If your main concern is the user not paying attention, then it's probably best to ask for confirmation. eg:

delete_cwd() {
        printf 'Are you sure you want to unlink everything in %s? ' "$(pwd)"
        IFS= read REPLY
        case $REPLY in
        [yY]|[yY]es) find . -delete;;
        *) return 1;;
        esac
}

Note that -delete is not standardized, so you may want to use:

find . ! -name . -exec rm -rf {} +

Or, if you want to force your user to confirm each removal, you could skip the function and just do:

find . ! -name . -depth -ok rm -rf {} +
  • Note that read -p prompt var is bash specific. Other shells (ksh/zsh) have read 'var?prompt' instead. POSIXly, you'd use printf 'Are you sure you want to unlink everything in %s? ' "$PWD"; IFS= read -r REPLY (also remember the behaviour of read depends on the current value of $IFS) – Stéphane Chazelas Apr 30 '19 at 15:44