【问题标题】:Finding empty directories查找空目录
【发布时间】:2011-02-18 03:28:02
【问题描述】:

我需要为给定的目录列表找到空目录。 有些目录里面有目录。

如果内部目录也是空的,我可以说主目录是空的,否则它不是空的。

我该如何测试?

例如:

A>A1(file1),A2 this is not empty beacuse of file1
B>B1(no file) this is empty
C>C1,C2 this is empty

【问题讨论】:

标签: bash unix directory


【解决方案1】:

这在一定程度上取决于您要如何处理空目录。当我希望删除树中的所有空目录时,我使用下面的命令,比如test 目录。

find test -depth -empty -delete

关于上述命令需要注意的一点是,它也会删除空文件,因此请使用 -type d 选项来避免这种情况。

find test -depth -type d -empty -delete

删除 -delete 以查看匹配的文件和目录。

如果您对空目录树的定义是它不包含文件,那么您可以根据find test -type f 是否返回任何内容来将某些内容粘贴在一起。

find 是一个很棒的实用程序,而且 RTFM 很早就并且经常能够真正了解它可以做多少:-)

【讨论】:

  • -delete 意味着-depth(至少对于 GNU findutils 4.4.2)
  • 不知道-empty,好方便!
  • 但是在不是最新最好的 linux 的机器上。 (EG Solaris),那么您就没有像 -empty 或 -delete 这样花哨的查找功能。
  • 在 MacOS-X 上,对于 几乎 个空目录,首先运行 find test -name ".DS_Store" -delete,然后运行 ​​-empty delete 命令。还要注意,喜欢pushd到父目录,这样find test就变成find .了,但是其余的命令都是一样的。
  • @Martin 能否请您在此处添加-depth 的定义,即 导致 find 执行深度优先遍历,即以后序访问目录和目录中的所有条目将在目录本身之前采取行动。我认为这与这里有关。
【解决方案2】:

您可以使用以下命令:

find . -type d -empty

【讨论】:

  • -empty 仅在当前目录完全为空时有效,如果子树不包含文件则无效。
  • @soField 测试 find 。 -type d -empty 与 FreeBSD 和 CentOS。工作正常。你的操作系统是什么?
  • hp-ux 所以没有空参数
  • @soField 所以,你看,最好(对我们所有人)在你的问题的顶部发布这些数据......
  • find 在 solaris 上也没有 -empty,但它确实有 -depth 来强制深度优先遍历,以便在检查父目录是否为空之前可以删除空子目录。
【解决方案3】:

检查find <dir> -type f 是否输出任何内容。这是一个例子:

for dir in A B C; do
    [ -z "`find $dir -type f`" ] && echo "$dir is empty"
done

【讨论】:

  • 不,它不会输出子目录。这就是-type f 的用途。
  • Howerver 如果有 空文件,您的解决方案将不会产生该消息。
  • Yasir:我认为包含空文件的目录本身不会是空的。这不是正确的结果吗?
  • @akostadinov:如果我按照 OP 的指示创建目录和文件 — mkdir A B C A/A1 A/A2 B/B1 C/C1 C/C2; touch A/A1/file1 — 并在我的答案中运行代码,它会报告 B 和 C 为空,这是 OP 要求的.因此,您需要比“它行不通”更具体一点。
  • 如果你像我一样是 Bash 菜鸟,请检查 -z 是什么意思 here
【解决方案4】:
find directory -mindepth 1 -type d -empty -delete

这是我觉得最有趣的版本。如果从目录内部执行,它将删除下面所有的空目录(如果一个目录只包含空目录,则认为它是空的)。

mindepth 选项可防止目录本身在碰巧为空时被删除。

【讨论】:

  • 您也可以通过rmdir --ignore-fail-on-non-empty -p directory 跟进以摆脱父母。
  • @Pete Peterson 我的命令似乎删除了只包含其他空目录的目录(这也是 OP 似乎也想要的)。我注意到您的命令通常会将用户留在缺少 i 节点的目录中,即使他们完成了他们想要的操作,这可能会让他们感到困惑。也许我没有抓住重点。
【解决方案5】:

find . -type d -empty

在当前树中查找并列出空目录和子目录。 例如。空目录和子目录的结果列表:

./2047
./2032
./2049
./2063
./NRCP26LUCcct1/2039
./NRCP26LUCcct1/2054
./NRCP26LUCcct1/2075
./NRCP26LUCcct1/2070

没有对目录进行任何操作。它们只是简单地列出来。 这对我有用。

【讨论】:

    【解决方案6】:

    只要找到空目录

    为了只找到空目录(在问题标题中指定),mosg's answer 是正确的:

    find -type d -empty
    

    -empty 可能不适用于非常旧的find 版本(例如HP-UX 的情况)。如果这是您的情况,请参阅下面部分中描述的技术目录是否为空?

    删除空目录

    这有点棘手:假设目录MyDir 包含空目录。删除这些空目录后,MyDir 将成为一个空目录,也应该删除。因此,我使用命令rmdir 和选项--parents(或-p),它也会尽可能删除父目录:

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

    在较旧的find 版本上,尚不支持声明+,因此您可以改用;

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

    目录是空的吗?

    这些答案中的大多数都解释了如何检查目录是否为空。因此,我在这里提供我知道的三种不同的技术:

    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
      

      变体:

      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
      

      说明:

      • find -prunefind -maxdepth 0 相似,使用更少的字符
      • find -type d 仅打印目录
      • find -empty 打印空目录和文件

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

      这个技巧是 100% bash 但调用(生成)一个子 shell。这个想法来自Bruno De Fraine,并由teambob 的评论改进。如果您使用 并且您的脚本不必是可移植的,我建议您使用这个。

      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
      

      注意:空目录和不存在的目录没有区别(即使提供的路径是文件)。

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

      这个技巧的灵感来自于 2007 年发布的 nixCraft's articleAndrew Taylor 于 2008 年回答,gr8can8dian 于 2011 年回答。

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

      或单行 bashism 版本:

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

      注意: 当目录不存在时,ls 返回$?=2。但是文件和空目录没有区别。

    【讨论】:

    • rmdir -vp 极大地帮助了我,因为我不仅需要删除根目录下的所有空目录,还需要在删除文件后检查空目录和父目录。在我的情况下,只要它们不在我当前正在从中删除文件的树中,空目录就可以了。谢谢!
    【解决方案7】:

    rmdir * 怎么样?该命令将在非空目录上失败。

    【讨论】:

    • 我有时会做一些事情,进行一般清理。还完成了rmdir */*/* */* * 之类的事情,尽管它不能处理“点文件”,但在手动情况下(清理数据文件),您通常不会期望“点文件”。然而,递归方法用于更自动化的常规清理,尤其是在非常大的目录结构中。
    • 在一种情况下更复杂,因为我需要删除空目录,其中“空”包含可能包含单个“自述文件”文件的目录。目录中的任何其他内容都不是“空的”。在该示例中,目录结构涉及数以万计的子目录。
    【解决方案8】:

    这个递归函数似乎可以解决问题:

    # 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
    }
    

    鉴于此示例目录结构:

    . |-- 目录1/ |-- 目录2/ | `--目录/ |-- 目录3/ | `--目录/ | `--文件5 |-- 目录4/ | |-- 目录/ | `--文件4 `--目录5/ `--目录/ `-- dir_V/

    运行该函数的结果是:

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

    错过了/dir4/dirD。如果将递归调用 findempty "$dir" 移到 fi 之后,该函数将在其结果中包含该目录。

    【讨论】:

      【解决方案9】:

      如果目录为空(或不存在),则以下命令返回 1,否则返回 0(因此可以在 shell 脚本中使用 ! 反转返回码):

      find $dir -type d -prune -empty -exec false {} +
      

      【讨论】:

        【解决方案10】:

        我创建了一个简单的结构如下:

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

        test/test3/file 包含一些垃圾文本。

        发出find test -empty 会返回“test/test2/test2.2”作为唯一的空目录。

        【讨论】:

        • 操作要求 test/test2 也返回
        • 确实如此。但我认为他可以阅读 find 手册页以更进一步。根据结果​​调整深度的脚本可以正常工作。
        • 这是我最有用的版本,谢谢
        【解决方案11】:

        一个简单的方法是,

        $ [ "$(ls -A /path/to/direcory)" ] && echo "not empty" || echo "its empty"
        

        还有,

        if [ "$(ls -A /path/to/direcory)" ]; then
           echo "its not empty"
        else 
           echo "empty directory"
        

        【讨论】:

          【解决方案12】:
          find . -name -type d -ls |awk '($2==0){print $11}'
          

          【讨论】:

            猜你喜欢
            • 2011-09-07
            • 2013-09-05
            • 2011-12-15
            • 1970-01-01
            • 2021-02-22
            • 1970-01-01
            • 2011-10-10
            • 1970-01-01
            • 2018-12-20
            相关资源
            最近更新 更多