18

gedit creates hidden backup files ending with '~'. I wanted to do a recursive cleanup of my directory tree.

The command rm *~ will delete all local files ending with '~'

I thought rm -r *~ . would delete all files in the whole tree, but I typo-ed rm -r ~.

There was a message some directory could not be deleted and I quit the command. The question is: What have I been deleting?

I did notice that my Filezilla configuration was gone. Does this command delete all hidden directories from the home dir?

10
  • 4
    Well, at least I have a backup strategy... No real harm done.
    – GUI Junkie
    Jun 29, 2012 at 9:10
  • 2
    Good to know; I have a policy of never using -r unless I want to get rid of everything.
    – ish
    Jun 29, 2012 at 9:15
  • 4
    As a side note, rm -r *~ . would delete all files and folders (in the current directory) matching *~ or .. (. would be ignored by rm as a special exception, as most people don't want to recursively delete the current directory. The *~ deletes all files and dirs in the current dir that end in ~, but not files and directories in subdirectories of the current directory.) So that's not what you would have wanted. You would probably have wanted to use find with the -exec flag to recursively look through the directory tree and non-recursively delete each file ending in ~. Jun 29, 2012 at 9:18
  • @EliahKagan, I guess so, but find with -exec is always a hassle. Restoring the home dir is more of a hassle, though :-)
    – GUI Junkie
    Jun 29, 2012 at 12:34
  • 1
    Informational: sing the ~ character without escaping it (like this: \~) will make Bash, ZSH, etc. (the rm command basically) think you mean the home directory.
    – Thomas Ward
    Jun 29, 2012 at 12:48

2 Answers 2

31

You have deleted (almost) all of your home directory!

rm -r something recursively deletes files and directories in/under something; it will only fail on items it does not have permission to delete, either because they are owned by a different user (e.g. root), or because they are in use (e.g. a GVFS mount).

If you did not add -f (as in, rm -rf something), you would get something like:

rm: remove write-protected regular file ‘something’?
rm: descend into write-protected directory ‘something’?

At this point you can abort and you then likely realise that you executed the wrong command.

Suggestions from the community on how to avoid such accidents

Note: Community wiki, everyone please feel free to contribute.

  • For a few files, use the -i option to get a confirmation on removing files or directories:

    $ rm -ri something/
    rm: remove regular file ‘something/file~’? y
    rm: descend into directory ‘something’? y
    rm: remove regular file ‘something/file’? y
    rm: remove directory ‘something’? y
    
  • If removing from a current directory, prefix it by a ./ to avoid mistakingly removing a different location.:

    $ cd something
    $ rm -v ./*~
    removed ‘./file~’
    

    The above was for demonstrating the use of ./. If there is a subdirectory, you can of course use rm -v something/*~ as well. Beware: do not think that rm ./.* removes all hidden files in the current directory. See this Serverfault question for workarounds on hidden files globbing.

  • Move rather than delete: Rather than deleting files recursively in the first place I got used to move the files I want to get rid of somewhere else before I delete them finally. If something went wrong its easy to restore.

    mv -b SOURCE DEST
    
  • Use find (possibly with grep) to preview if you want to recursively delete selected files. You should try to make this a rare occurrence, but if you have to...

    1. find with no arguments recursively lists all files/directories under the current one. You should try to look up man find on how to make it selective (a treasure trove), but if you don't want to bother, you can just use the familiar grep to filter for the files you want to delete.
    2. Suppose I'm an uber-l33t kernel hacker, and am bothered by the few KBs of "example" files in my source tree; I want to delete all files containing that in the name. So I type find | grep example, which gives me these 20 files. That looks good, so I now go and delete those exact files, along with the rm -v verbose output previously mentioned, via xargs:
      find | grep example | xargs rm -v
      which gives me this output. Such previewing prevents problems where say, you make a typo and type sample instead of example.

The above solution should not be used if you may have filenames containing spaces, tab characters, newlines, or quotes (" or '), as this will lead xargs to either fail, or feed rm with incomplete filenames, which in worst case could end up removing the wrong files. The safe way to do the above is to do it all with find's operators and actions.

The following will show all files that contain the word example

find . -name "*example*"  

If that list is the files you want to remove, use the -exec action to pass the files to rm.

find . -name "*example*" -exec rm -v {} +

See Using Find for more help with using find.

8
  • 1
    piping find output to grep and xargs rm is dangerous.
    – geirha
    Jun 29, 2012 at 9:00
  • 2
    @izx: added mv (my favourite command) ;)
    – Takkat
    Jun 29, 2012 at 9:35
  • 1
    I'd at least add an example of using find the safe way, one that doesn't break (and potentially delete the wrong files) if filenames contain space, tab, newline, " or ' characters. E.g. find . -name "*example*" -exec rm -v {} +. mywiki.wooledge.org/UsingFind
    – geirha
    Jun 29, 2012 at 10:45
  • 1
    @geirha: why is find -delete so dangerous? I would have said something here but I don't know other than it recently found and wiped my / despite a dry run without option -delete only found few files that I wanted to remove. I see that you recommend -exec rm instead.
    – Takkat
    Jun 30, 2012 at 10:25
  • 3
    @Takkat -delete is not dangerous, and you can safely use it instead of -exec rm {} +. I generally prefer to use standard tools and features when possible. -delete is a non-standard, GNU extension to find, so it'll work fine on Ubuntu, but may not on other systems.
    – geirha
    Jun 30, 2012 at 10:35
5

Yes. An unquoted tilde character as a separate argument gets expanded to your homedir. So rm -r ~ got expanded to rm -r /home/yourusename. So you told rm to recursively delete all files in your homedir.

See http://www.gnu.org/software/bash/manual/bashref.html#Tilde-Expansion for more about how tilde expansion works.

You must log in to answer this question.

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