【问题标题】:Checking from shell script if a directory contains files从 shell 脚本检查目录是否包含文件
【发布时间】:2026-01-23 02:15:01
【问题描述】:

如何通过 shell 脚本检查目录是否包含文件?

类似的东西

if [ -e /some/dir/* ]; then echo "huzzah"; fi;

但如果目录包含一个或多个文件(上述文件仅适用于恰好 0 或 1 个文件),则此方法有效。

【问题讨论】:

  • @DaveWebb 不,它没有。如果 glob 扩展到多个单词,zsh 测试会报告“测试:参数太多”。
  • “huzzah”表示“目录不为空”。
  • 如果目录只包含一个空的子目录,是否算“包含文件”?

标签: bash unix shell


【解决方案1】:

试试:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi

【讨论】:

  • 这对我有用,但我无法格式化这个 d*mn 消息!!!
    导出 tmp=/bin/ls <some_dir>/* 2> /dev/null if [ ! -z "$tmp" ];然后 echo 那里有东西
  • 对于像我这样的 Bash 白痴,如果您想检查相反的内容 - 目录是否为空 - 只需使用 if [ -z ls /some/dir/* ];然后回显“huzzah”;菲
  • 您可以使用-n 代替! -z(它们是等价的,但是如果存在较短的形式,为什么不使用它)。
  • 在 ZSH 这个例子中抛出一个错误,想法是不抛出错误...BigGray% if [ ! -z ls /some/dir/*` ];然后回显“huzzah”; fi zsh:未找到匹配项:/some/dir/* `
  • 在 bash 中没有双引号 ls... 对我不起作用
【解决方案2】:
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi

【讨论】:

    【解决方案3】:

    你能比较一下这个的输出吗?

     ls -A /some/dir | wc -l
    

    【讨论】:

      【解决方案4】:
      if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
      

      【讨论】:

      • 我喜欢这个,因为命令中没有引号或括号。
      • 如果你设置了nullglob,请注意不要使用这个,因为这样ls 命令就会成功。
      • 如果目录有点文件,则不适用于所有环境。
      【解决方案5】:

      目前的解决方案使用ls。这是一个全 bash 解决方案:

      #!/bin/bash
      shopt -s nullglob dotglob     # To include hidden files
      files=(/some/dir/*)
      if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
      

      【讨论】:

      • 只要你记得在脚本结束时将选项设置回它们的原始值 :)
      • 为什么不使用子shell来重置设置:files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
      • @teambob 如果使用子 shell:files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*) 那么 if 语句应该更改为 if [ ${#files} -gt 0 ]; 或者您可能只是忘记了子 shell 命令周围的 ()? files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
      • @stoutyhk $(...) 恢复设置,不需要单独的子shell。使用 $(...) 会生成一个新的 shell 实例。一旦命令完成,这个新实例的环境就会被丢弃。编辑:找到参考 tldp.org/LDP/abs/html/commandsub.html“命令替换调用子shell。”
      • 您可以将其全部保存在 if 测试中,不需要数组:if [ -z $(shopt -s nullglob dotglob; echo /some/dir/*) ]; then my_stuff; fi,也许使用布尔运算符的短路技巧。将其包装在一个函数中以提高可读性。
      【解决方案6】:

      以下内容如何:

      if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
      

      这样就不需要生成目录内容的完整列表。 read 既要丢弃输出,又要使表达式仅在读取某些内容时才评估为真(即 find 发现 /some/dir/ 为空)。

      【讨论】:

      • 或者干脆find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
      • +1 这是最优雅的解决方案。它不涉及解析ls 输出,也不依赖非默认shell 功能。
      • 不过,它确实依赖于非标准的 -maxdepth-empty 原色。
      • 这个也可以区分它是否是一个实际的目录。如果它是空的,它不会告诉它是否是一个文件!太棒了!
      【解决方案7】:

      请注意包含大量文件的目录!评估ls 命令可能需要一些时间。

      IMO 最好的解决方案是使用

      find /some/dir/ -maxdepth 0 -empty
      

      【讨论】:

        【解决方案8】:

        这可能是一个非常晚的响应,但这是一个有效的解决方案。此行仅识别文件的存在!如果目录存在,它不会给你一个误报。

        if find /path/to/check/* -maxdepth 0 -type f | read
          then echo "Files Exist"
        fi
        

        【讨论】:

          【解决方案9】:
          # 检查目录是否包含任何非隐藏文件。 # # 用法: if isempty "$HOME";然后回显“欢迎回家”;菲 # 是空的() { 对于 $1/* 中的 _ief;做 如果 [ -e "$_ief" ];然后 返回 1 菲 完毕 返回 0 }

          一些实现说明:

          • for 循环避免调用外部ls 进程。它仍然读取所有目录条目一次。这只能通过编写显式使用 readdir() 的 C 程序来优化。
          • 循环内的test -e 捕获空目录的情况,在这种情况下,变量_ief 将被赋值为“somedir/*”。仅当该文件存在时,该函数才会返回“非空”
          • 此功能适用于所有 POSIX 实现。但请注意,Solaris /bin/sh 不属于该类别。它的test 实现不支持-e 标志。

          【讨论】:

          • 如果未设置dotglob,这将忽略目录中的点文件 - shopt -s dotglob
          【解决方案10】:
          # Works on hidden files, directories and regular files
          ### isEmpty()
          # This function takes one parameter:
          # $1 is the directory to check
          # Echoes "huzzah" if the directory has files
          function isEmpty(){
            if [ "$(ls -A $1)" ]; then
              echo "huzzah"
            else 
              echo "has no files"
            fi
          }
          

          【讨论】:

            【解决方案11】:

            我不喜欢发布的ls - A 解决方案。您很可能希望测试该目录是否为空,因为您不想删除它。以下是这样做的。但是,如果您只想记录一个空文件,那么删除和重新创建它肯定比列出可能无限的文件更快吗?

            这应该可以工作......

            if !  rmdir ${target}
            then
                echo "not empty"
            else
                echo "empty"
                mkdir ${target}
            fi
            

            【讨论】:

            • 如果用户没有${target}/..的写权限,这不起作用。
            • 使测试具有破坏性是个坏主意。除此之外,它还引入了竞争条件。
            【解决方案12】:

            测试特定的目标目录

            if [ -d $target_dir ]; then
                ls_contents=$(ls -1 $target_dir | xargs); 
                if [ ! -z "$ls_contents" -a "$ls_contents" != "" ]; then
                    echo "is not empty";
                else
                    echo "is empty";
                fi;
            else
                echo "directory does not exist";
            fi;
            

            【讨论】:

              【解决方案13】:

              三个最佳技巧


              shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))

              这个技巧是 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
              

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

              'official' FAQ for #bash IRC channel 上有类似的替代方案和更多详细信息(以及更多示例):

              if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
              then
                echo "contains files"
              else 
                echo "empty (or does not exist, or is a file)"
              fi
              

              [ -n "$(ls -A your/dir)" ]

              这个技巧的灵感来自于 2007 年发布的 nixCraft's article。添加 2>/dev/null 以抑制输出错误 "No such file or directory"
              另请参阅 Andrew Taylor 的答案 (2008) 和 gr8can8dian'我的回答(2011 年)。

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

              或单行 bashism 版本:

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

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


              [ -n "$(find your/dir -prune -empty)" ]

              最后一个技巧的灵感来自gravstar's answer,其中-maxdepth 0-prune 替换,并由phils 的评论改进。

              if [ -n "$(find your/dir -prune -empty 2>/dev/null)" ]
              then
                echo "empty (directory or file)"
              else
                echo "contains files (or does not exist)"
              fi
              

              使用-type d的变体:

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

              说明:

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

              注意:您也可以将[ -n "$(find your/dir -prune -empty)" ] 替换为下面的缩短版本:

              if [ `find your/dir -prune -empty 2>/dev/null` ]
              then
                echo "empty (directory or file)"
              else
                echo "contains files (or does not exist)"
              fi
              

              最后一段代码在大多数情况下都有效,但请注意恶意路径可能会表达命令...

              【讨论】:

              • 我觉得可以把find选项简化为[ -n "$(find "your/dir" -prune -empty)" ],避免目录路径的重复。
              • 在脚本中使用if [ ``ls -A your/dir`` ] 时,我得出的结论是,它适用于具有 0、1 或 2 个子目录的目录,但对于具有 2 个以上子目录的目录则失败。 line 17: [: 20150424-002813: unary operator expected 其中20150424-002813 是目录名称之一。使用的外壳是/bin/bash/。我终于改成了ls "$destination" | tail -1
              • 嗨@ChristopheDeTroyer 我无法重现您的问题。在我这边if [ ``ls -A my/dir`` ] 退出错误bash: [: -A: binary operator expected。在 bash 版本 4.1.2 和 4.2.53 上测试。
              • 好吧,我主要是因为感知到的不一致而发表评论的(因为 -n 变体在标题中,但不在下面的段落中)。所以,是的,没关系。
              • 我正在使用你的 -n 解决方案,但我的脚本仍然抱怨这个ls: cannot access '/path': No such file or directory。有没有办法可以抑制这个消息?我想在那里默默地失败。
              【解决方案14】:

              我很惊讶wooledge guide on empty directories 没有被提及。本指南以及所有有关毛边的内容,对于 shell 类型的问题都是必读的。

              该页面的注意事项:

              永远不要尝试解析 ls 输出。即使是 ls -A 解决方案也可能会中断(例如,在 HP-UX 上,如果您是 root,则 ls -A 会 如果您不是 root,则与它的作用完全相反-不,我无法弥补 非常愚蠢)。

              事实上,人们可能希望完全避免直接问题。通常人们想知道一个 目录是空的,因为他们想做一些涉及其中文件的事情,等等。看看更大的 题。例如,这些基于查找的示例之一可能是合适的解决方案:

                 # Bourne
                 find "$somedir" -type f -exec echo Found unexpected file {} \;
                 find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \;  # GNU/BSD
                 find "$somedir" -type d -empty -exec cp /my/configfile {} \;   # GNU/BSD
              

              最常见的是,真正需要的是这样的:

                 # Bourne
                 for f in ./*.mpg; do
                      test -f "$f" || continue
                      mympgviewer "$f"
                  done
              

              换句话说,提出问题的人可能认为明确的空目录测试是 需要避免类似 mympgviewer: ./*.mpg: No such file or directory 而实际上没有的错误消息 需要这样的测试。

              【讨论】:

                【解决方案15】:

                到目前为止,我还没有看到使用 grep 的答案,我认为它会给出更简单的答案(没有太多奇怪的符号!)。这就是我的方式 使用 bourne shell 检查目录中是否存在任何文件:

                这将返回目录中的文件数:

                ls -l <directory> | egrep -c "^-"
                

                可以在写入目录的地方填写目录路径。管道的前半部分确保每个文件的输出的第一个字符是“-”。 egrep 然后计算以它开头的行数 使用正则表达式的符号。现在您所要做的就是存储您获得的数字并使用反引号进行比较,例如:

                 #!/bin/sh 
                 fileNum=`ls -l <directory> | egrep -c "^-"`  
                 if [ $fileNum == x ] 
                 then  
                 #do what you want to do
                 fi
                

                x 是您选择的变量。

                【讨论】:

                  【解决方案16】:
                  dir_is_empty() {
                     [ "${1##*/}" = "*" ]
                  }
                  
                  if dir_is_empty /some/dir/* ; then
                     echo "huzzah"
                  fi
                  

                  假设你没有一个名为 * 的文件到 /any/dir/you/check,它应该在 bash dash posh busybox shzsh 上工作,但(对于 zsh)需要 unsetopt nomatch

                  性能应该与使用*(glob) 的任何ls 相当,我猜在有许多节点的目录上会很慢(我的/usr/bin 有3000+ 个文件并没有那么慢),至少会使用内存足以分配所有目录/文件名(以及更多),因为它们都作为参数传递(解析)给函数,某些 shell 可能对参数数量和/或参数长度有限制。

                  如果有一个可移植的快速 O(1) 零资源方法来检查目录是否为空,那就太好了。

                  更新

                  以上版本不考虑隐藏文件/目录,以防需要更多测试,例如来自Rich’s sh (POSIX shell) tricksis_empty

                  is_empty () (
                  cd "$1"
                  set -- .[!.]* ; test -f "$1" && return 1
                  set -- ..?* ; test -f "$1" && return 1
                  set -- * ; test -f "$1" && return 1
                  return 0 )
                  

                  但是,相反,我正在考虑这样的事情:

                  dir_is_empty() {
                      [ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
                  }
                  

                  当 dir 为空时,一些关于尾随斜杠与参数和 find 输出的差异的担忧,以及尾随换行符(但这应该很容易处理),遗憾的是我的 busybox sh 显示什么可能是一个错误在find -&gt; dd 管道上,输出被随机截断(如果我使用cat,输出总是相同的,似乎是ddcount 参数)。

                  【讨论】:

                  • 我喜欢便携式解决方案。我来给同样的答案。我刚刚以不同的方式编写了它(如果不是目录,则返回 2)。此外,这些可移植解决方案的优点是不调用任何外部程序,这对于受限或嵌入式系统可能算得上是一个加分项。我只是担心使用“()”可能会创建一个新的子进程(或者至少强制复制环境和内容然后切换回来)。看看这个: is_empty(){ _d="${1:-.}"; [ ! -d "${_d}" ] && return 2;set -- "${_d}"/* "${_d}"/.[!.]* "${_d}"/..?*; [ "${}" = "${_d}/ ${_d}/.[!.]* ${_d}/..?*" ]; };
                  • @DiegoAugustoMolina 最近在一个项目中我不得不再次做这个测试,如果一个目录是空的,一开始我使用python,然后因为我实际上安装了python,所以我在c,实现非常平庸,我想知道为什么它从未作为测试或作为独立命令添加
                  • 我最近也需要针对(真正)受限系统的这个问题的解决方案。我什至对前面的代码进行了一些优化,根本不使用额外的变量。黑客和丑陋的单线但很棒。为自己服务:is_empty(){ [ ! -d "${1}" ] &amp;&amp; return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
                  【解决方案17】:

                  这对我很有效(当目录存在时):

                  some_dir="/some/dir with whitespace & other characters/"
                  if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
                  

                  全面检查:

                  if [ -d "$some_dir" ]; then
                    if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; else "Dir is NOT empty" fi
                  fi
                  

                  【讨论】:

                    【解决方案18】:

                    这告诉我目录是否为空,如果不是,它包含的文件数。

                    directory="/some/dir"
                    number_of_files=$(ls -A $directory | wc -l)
                    
                    if [ "$number_of_files" == "0" ]; then
                        echo "directory $directory is empty"
                    else
                        echo "directory $directory contains $number_of_files files"
                    fi
                    

                    【讨论】:

                    • 谁能解释我为什么被否决?如果我在写花旗骰,我想知道为什么;)
                    • 我没有对此投反对票,但猜测是因为你是parsing the output of ls
                    • 链接的文章不清楚吗?如果是这样,请给作者(不是我)发电子邮件。
                    • @TobySpeight 我明白了。但在这种情况下,我计算的是没有枚举它们的行。仅当文件名包含新行时,它才会给出错误结果。如果文件名包含新行,那么更重要的东西一定是在某个地方搞砸了;)
                    【解决方案19】:

                    Bruno's answer 的小变化:

                    files=$(ls -1 /some/dir| wc -l)
                    if [ $files -gt 0 ] 
                    then
                        echo "Contains files"
                    else
                        echo "Empty"
                    fi
                    

                    对我有用

                    【讨论】:

                      【解决方案20】:

                      混合修剪的东西和最后的答案,我必须

                      find "$some_dir" -prune -empty -type d | read && echo empty || echo "not empty"
                      

                      也适用于带空格的路径

                      【讨论】:

                        【解决方案21】:

                        bash 的简单回答:

                        if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
                        

                        【讨论】:

                          【解决方案22】:

                          我会选择find:

                          if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
                              echo "$dir has NO files"
                          else
                              echo "$dir has files"
                          

                          这会检查仅在目录中查找文件的输出,而不通过子目录。然后它使用取自man test-z 选项检查输出:

                             -z STRING
                                    the length of STRING is zero
                          

                          查看一些结果:

                          $ mkdir aaa
                          $ dir="aaa"
                          

                          空目录:

                          $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
                          empty
                          

                          只是目录:

                          $ mkdir aaa/bbb
                          $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
                          empty
                          

                          目录中的一个文件:

                          $ touch aaa/myfile
                          $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
                          $ rm aaa/myfile 
                          

                          子目录中的文件:

                          $ touch aaa/bbb/another_file
                          $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
                          empty
                          

                          【讨论】:

                            【解决方案23】:

                            尝试使用命令查找。 指定硬编码的目录或作为参数。 然后启动 find 搜索目录内的所有文件。 检查 find 的返回是否为空。 回显 find 的数据

                            #!/bin/bash
                            
                            _DIR="/home/user/test/"
                            #_DIR=$1
                            _FIND=$(find $_DIR -type f )
                            if [ -n "$_FIND" ]
                            then
                               echo -e "$_DIR contains files or subdirs with files \n\n "
                               echo "$_FIND"
                            else
                            echo "empty (or does not exist)"
                            fi
                            

                            【讨论】:

                            • 如果目录中有空目录或非常规文件(套接字、字符设备、符号链接等),这将不起作用。该目录将被报告为空。
                            • @DiegoAugustoMolina 如果我在问题中理解正确,我们正在检查文件是否存在(作为文字文件),这就是使用 -f 参数的原因。但你的 cmets 仍然是正确的。
                            【解决方案24】:

                            ZSH

                            我知道这个问题被标记为 bash;但是,仅供参考,zsh 用户:

                            测试非空目录

                            检查foo 是否为非空:

                            $ for i in foo(NF) ; do ... ; done
                            

                            如果foo 不为空,则for 块中的代码将被执行。

                            测试空目录

                            检查foo是否为空:

                            $ for i in foo(N/^F) ; do ... ; done
                            

                            如果foo为空,则for块中的代码将被执行。

                            注意事项

                            我们不需要引用上面的目录foo,但如果需要,我们可以这样做:

                            $ for i in 'some directory!'(NF) ; do ... ; done
                            

                            我们还可以测试多个对象,即使它不是一个目录:

                            $ mkdir X     # empty directory
                            $ touch f     # regular file
                            $ for i in X(N/^F) f(N/^F) ; do echo $i ; done  # echo empty directories
                            X
                            

                            任何不是目录的东西都将被忽略。

                            附加功能

                            由于我们是 glob,我们可以使用任何 glob(或大括号扩展):

                            $ mkdir X X1 X2 Y Y1 Y2 Z
                            $ touch Xf                    # create regular file
                            $ touch X1/f                  # directory X1 is not empty
                            $ touch Y1/.f                 # directory Y1 is not empty
                            $ ls -F                       # list all objects
                            X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
                            $ for i in {X,Y}*(N/^F); do printf "$i "; done; echo  # print empty directories
                            X X2 Y Y2
                            

                            我们还可以检查放置在数组中的对象。以上述目录为例:

                            $ ls -F                       # list all objects
                            X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
                            $ arr=(*)                     # place objects into array "arr"
                            $ for i in ${^arr}(N/^F); do printf "$i "; done; echo
                            X X2 Y Y2 Z
                            

                            因此,我们可以测试可能已经在数组参数中设置的对象。

                            请注意,for 块中的代码显然是依次在每个目录上执行的。如果这不是可取的,那么您可以简单地填充一个数组参数,然后对该参数进行操作:

                            $ for i in *(NF) ; do full_directories+=($i) ; done
                            $ do_something $full_directories
                            

                            说明

                            对于 zsh 用户,有 (F) glob 限定符(参见 man zshexpn),它匹配“完整”(非空)目录:

                            $ mkdir X Y
                            $ touch Y/.f        # Y is now not empty
                            $ touch f           # create a regular file
                            $ ls -dF *          # list everything in the current directory
                            f X/ Y/
                            $ ls -dF *(F)       # will list only "full" directories
                            Y/
                            

                            限定符(F) 列出匹配的对象: 是一个目录并且不为空。所以,(^F) 匹配:不是目录或为空。因此,例如,单独的(^F) 也会列出常规文件。因此,正如zshexp 手册页所述,我们还需要(/) glob 限定符,它只列出目录:

                            $ mkdir X Y Z
                            $ touch X/f Y/.f    # directories X and Y now not empty
                            $ for i in *(/^F) ; do echo $i ; done
                            Z
                            

                            因此,要检查给定目录是否为空,您可以运行:

                            $ mkdir X
                            $ for i in X(/^F) ; do echo $i ; done ; echo "finished"
                            X
                            finished
                            

                            只是为了确保不会捕获非空目录:

                            $ mkdir Y
                            $ touch Y/.f
                            $ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
                            zsh: no matches found: Y(/^F)
                            finished
                            

                            哎呀!由于Y 不为空,zsh 没有找到(/^F) 的匹配项(“为空的目录”),因此会吐出一条错误消息,指出未找到 glob 的匹配项。因此,我们需要使用(N) glob 限定符来抑制这些可能的错误消息:

                            $ mkdir Y
                            $ touch Y/.f
                            $ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
                            finished
                            

                            因此,对于空目录,我们需要限定符 (N/^F),您可以将其解读为:“不要警告我失败,目录未满”。

                            同样,对于非空目录,我们需要限定符 (NF),我们也可以将其读作:“不要警告我失败,完整目录”。

                            【讨论】:

                              【解决方案25】:

                              通过一些解决方法,我可以找到一种简单的方法来确定目录中是否有文件。这可以通过 grep 命令进行更多扩展,以专门检查 .xml 或 .txt 文件等。例如:ls /some/dir | grep xml | wc -l | grep -w "0"

                              #!/bin/bash
                              if ([ $(ls /some/dir | wc -l  | grep -w "0") ])
                                  then
                                      echo 'No files'
                                  else
                                      echo 'Found files'
                              fi
                              

                              【讨论】:

                                【解决方案26】:

                                从 olibre 的回答中得到一个(或几个)提示,我喜欢 Bash 函数:

                                function isEmptyDir {
                                  [ -d $1 -a -n "$( find $1 -prune -empty 2>/dev/null )" ]
                                }
                                

                                因为虽然它创建了一个子外壳,但它与我想象的 O(1) 解决方案一样接近,并且给它一个名称使其可读。然后我可以写

                                if isEmptyDir somedir
                                then
                                  echo somedir is an empty directory
                                else
                                  echo somedir does not exist, is not a dir, is unreadable, or is  not empty
                                fi
                                

                                至于 O(1) 存在异常情况:如果一个大目录已删除所有或除最后一个条目之外的所有内容,“查找”可能必须读取整个内容以确定它是否为空。我相信预期的性能是 O(1),但最坏的情况是目录大小是线性的。我没有测量过这个。

                                【讨论】:

                                  【解决方案27】:

                                  在另一个帖子How to test if a directory is empty with find我提出了这个

                                  [ "$(cd $dir;echo *)" = "*" ] && echo empty || echo non-empty
                                  

                                  理由是,$dir 确实存在,因为问题是“从 shell 脚本检查目录是否包含文件”,并且 * 即使在大目录上也没有那么大,在我的系统上 /usr/bin/* 是只有 12Kb。

                                  更新:感谢@hh skladby,已修复。

                                  [ "$(cd $dir;echo .* *)" = ". .. *" ] && echo empty || echo non-empty
                                  

                                  【讨论】:

                                  • 思路很完美,但是你错过了点文件。在单行中搜索点文件和非点文件是一项任务。
                                  • 哎哟 :-) 好的,那么可能是 [ "$(cd $dir;echo .* *)" = "... *" ] && echo empty ||回显非空
                                  【解决方案28】:
                                  if [[ -s somedir ]]; then
                                      echo "Files present"
                                  fi
                                  

                                  在我使用 bash 5.0.17 进行的测试中,如果 somedir 有任何孩子,[[ -s somedir ]] 将返回 true。 [ -s somedir ] 也是如此。请注意,如果存在隐藏文件或子目录,这也将返回 true。它也可能依赖于文件系统。

                                  【讨论】:

                                    【解决方案29】:

                                    没有calling utils like ls,查找等:

                                    POSIX 安全,即不依赖于您的 Bash / xyz shell / ls / 等版本:

                                    dir="/some/dir"
                                    [ "$(echo $dir/*)x" != "$dir/*x" ] || [ "$(echo $dir/.[^.]*)x" != "$dir/.[^.]*x" ] || echo "empty dir"
                                    

                                    想法:

                                    • echo * 列出非点文件
                                    • echo .[^.]* 列出“.”以外的点文件和“..”
                                    • 如果echo 没有找到匹配项,则返回搜索表达式,即此处*.[^.]* - 两者都不是真正的字符串,必须与例如连接。一个字母来强制一个字符串
                                    • || 替换 short circuit 中的可能性:至少有一个非点文件或目录或至少一个点文件或目录或目录为空 - 在执行级别:“如果第一种可能性失败,请尝试下一个,如果失败,请尝试下一个";从技术上讲,这里是 Bash “尝试执行”echo "empty dir",将您对空目录的操作放在这里(例如退出)。

                                    已检查符号链接,但尚未检查更奇异的可能文件类型。

                                    【讨论】:

                                    最近更新 更多