Finding empty directories UNIX

后端 未结 12 625
心在旅途
心在旅途 2020-12-07 14:11

I need to find empty directories for a given list of directories. Some directories have directories inside it.

If inside directories are also empty I can say main di

相关标签:
12条回答
  • 2020-12-07 14:42

    I created a simple structure as follows:

    test/
    test/test2/
    test/test2/test2.2/
    test/test3/
    test/test3/file
    

    The test/test3/file contains some junk text.

    Issuing find test -empty returns "test/test2/test2.2" as the only empty directory.

    0 讨论(0)
  • 2020-12-07 14:46

    Just find empty dirs

    In order to just find empty directories (as specified in the question title), the mosg's answer is correct:

    find -type d -empty
    

    But -empty may not be available on very old find versions (this is the case of HP-UX for example). If this is your case, see the techniques described in below section Is a directory empty?.

    Delete empty dirs

    This is a bit tricky: Suppose a directory MyDir contains empty directories. After removing these empty directories, MyDir will become an empty directory and should also be removed. Therefore I use the command rmdir with the option --parents (or -p) that also removes parent directories when possible:

    find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} +
    

    On older find version the statement + is not yet supported, therefore you may use ; instead:

    find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} `;`
    

    Is a directory empty?

    Most of these answers explain how to check if a directory is empty. Therefore I provide here the three different techniques I know:

    1. [ $(find your/dir -prune -empty) = your/dir ]

      d=your/dir
      if [ x$(find "$d" -prune -empty) = x"$d" ]
      then
        echo "empty (directory or file)"
      else
        echo "contains files (or does not exist)"
      fi
      

      a variation:

      d=your/dir
      if [ x$(find "$d" -prune -empty -type d) = x"$d" ]
      then
        echo "empty directory"
      else
        echo "contains files (or does not exist or is not a directory)"
      fi
      

      Explanation:

      • find -prune is similar than find -maxdepth 0 using less characters
      • find -type d prints directories only
      • find -empty prints the empty directories and files

        > mkdir -v empty1 empty2 not_empty
        mkdir: created directory 'empty1'
        mkdir: created directory 'empty2'
        mkdir: created directory 'not_empty'
        > touch not_empty/file
        > find empty1 empty2 not_empty -prune -empty
        empty1
        empty2
        
    2. (( ${#files} ))

      This trick is 100% bash but invokes (spawns) a sub-shell. The idea is from Bruno De Fraine and improved by teambob's comment. I advice this one if you use bash and if your script does not have to be portable.

      files=$(shopt -s nullglob dotglob; echo your/dir/*)
      if (( ${#files} ))
      then 
        echo "contains files"
      else 
        echo "empty (or does not exist or is a file)"
      fi
      

      Note: no difference between an empty directory and a non-existing one (and even when the provided path is a file).

    3. [ $(ls -A your/dir) ]

      This trick is inspired from nixCraft's article posted in 2007. Andrew Taylor answered in 2008 and gr8can8dian in 2011.

      if [ "$(ls -A your/dir)" ]
      then
        echo "contains files"
      else
        echo "empty (or does not exist or is a file)"
      fi
      

      or the one-line bashism version:

      [[ "$(ls -A your/dir)" ]] && echo "contains files" || echo "empty or ..."
      

      Note: ls returns $?=2 when the directory does not exist. But no difference between a file and an empty directory.

    0 讨论(0)
  • 2020-12-07 14:46
    find . -name -type d -ls |awk '($2==0){print $11}'
    
    0 讨论(0)
  • 2020-12-07 14:55

    How about rmdir *? That command will fail on non-empty directories.

    0 讨论(0)
  • 2020-12-07 14:56
    find directory -mindepth 1 -type d -empty -delete
    

    This is the version that I found most interesting. If executed from inside directory, it will delete all empty directories below (a directory is considered empty if it only contains empty directories).

    The mindepth option prevents the directory itself from being deleted if it happens to be empty.

    0 讨论(0)
  • 2020-12-07 14:56

    This recursive function would seem to do the trick:

    # Bash
    findempty() {
        find ${1:-.} -mindepth 1 -maxdepth 1 -type d | while read -r dir
        do
            if [[ -z "$(find "$dir" -mindepth 1 -type f)" ]] >/dev/null
            then
                findempty "$dir"
                echo "$dir"
            fi
        done
    }
    

    Given this example directory structure:

        .
        |-- dir1/
        |-- dir2/
        |   `-- dirB/
        |-- dir3/
        |   `-- dirC/
        |       `-- file5
        |-- dir4/
        |   |-- dirD/
        |   `-- file4
        `-- dir5/
            `-- dirE/
                `-- dir_V/
    

    The result of running that function would be:

        ./dir1
        ./dir5/dirE/dir_V
        ./dir5/dirE
        ./dir5
        ./dir2/dirB
        ./dir2
    

    which misses /dir4/dirD. If you move the recursive call findempty "$dir" after the fi, the function will include that directory in its results.

    0 讨论(0)
提交回复
热议问题