Search code examples
bashdirectorytruncate

Truncate a directory in bash


Is there some elegant/simple way to delete the folder's contents in such a way there's no error output if it is empty?

The following command

$ rm -r $dir/*   

doesn't work if the directory is empty, since in such a case, the wilcard * is not expanded and you get an error saying that rm cannot find file *.

Of course, the standard way is check if it is empty (with ls $dir | wc -w or find $dir -link 2 or any other related command), and deleting its contents otherwise.

Is there an alternative way not to check folder contents and only "truncate" the directory instead?


Solution

  • Bash

    Simply,

    $ rm -rf dir/*
    

    (By default I believe) Bash doesn't complain about not finding anything with the glob. It just passes your literal glob through to your command:

    $ echo dir/*
    dir/*
    

    When rm doesn't find a filename that has the literal glob character, it complains about not finding the file it's been asked to delete:

    $ rm "dir/*"
    rm: cannot remove ‘dir/*’: No such file or directory
    $ echo $?
    1
    

    But if you force it, it won't complain:

    $ rm -f "dir/*"
    $ echo $?
    0
    

    I don't know if that refrain-from-complain is POSIX.

    Do note, however, that if you don't have the shell option "dotglob" set, you'll miss files that start with a dot, AKA "hidden" files.

    Generally

    Zsh doesn't pass the literal glob through by default. You have to ask for it with "set -o nonomatch".

    $ echo dir/*
    zsh: no matches found: dir/*
    $ echo $?
    1
    $ set -o nonomatch
    $ echo dir/*
    dir/*
    

    For compatibility, I wouldn't use the above modern-Bash-specific "rm -rf dir/*", but would use the more general, widely-compatible solution:

    $ find dir -mindepth 1 -delete
    

    Find all files in "dir" at a minimum depth of 1 ("dir" itself is at depth 0), and delete them.