【问题标题】:How to check if folder is empty or have folder file use shell-script? [duplicate]如何检查文件夹是否为空或文件夹文件是否使用shell脚本? [复制]
【发布时间】:2010-11-23 07:25:56
【问题描述】:

我有一个问题

我尝试了一些类似的功能

DIR=/path/tmp/

如果 [ -d "$DIR" ];那么

如果 [ -f "$DIR" ];那么

但只检查 /path/tmp 这个路径

我该怎么办?

【问题讨论】:

    标签: linux shell


    【解决方案1】:

    rmdir "$DIR"

    如果$? 为1,则目录不为空。如果为 0,则为空并被删除。

    如果您不打算删除它,可以重新创建它:mkdir "$DIR"

    【讨论】:

    • 他没有说要删除目录。删除它只是为了确定它是否为空是一个非常糟糕的主意。
    • 因为您要删除目录,而他并没有说他想这样做。也许还有另一个进程即将写入目录。也许他没有权利删除它。关键是,这是一种破坏性操作,并且不是必需的。
    • 公平地说,我认为这个答案仍然有用。也许有人正在用一个用例来看待这个问题,其中破坏性的尝试删除然后重新创建的东西不是问题,并且这种方法有 simplicity 其他方法只是没有。
    【解决方案2】:

    来自Bash FAQ #4 -- 如何检查目录是否为空?

    shopt -s nullglob dotglob
    files=(*)
    (( ${#files[*]} )) || echo directory is empty
    shopt -u nullglob dotglob
    

    这个小脚本用在路径扩展* 中找到的每个文件填充数组files。然后它会检查数组的大小,如果它为 0,则打印“目录为空”。由于使用了dotglob,这将适用于隐藏文件。

    注意

    要求解析ls 的答案通常是一个坏主意和糟糕的形式。要了解原因,请阅读Why you shouldn't parse the output of ls

    【讨论】:

    • +1 表示非ls 解决方案,但请注意我的答案 解析ls 的输出。它只是检查它是否有。 :-)
    • 如果我想在 php systen() 中使用它;可以用吗?
    • 另一个问题文件可以使用路径吗?
    • 如果目录包含大量条目(名称很长),这将是不利的,因为它将所有条目加载到内存中只是为了检查是否有任何条目。
    【解决方案3】:
    [ -z "$(find "$DIR" -maxdepth 0 -empty)" ] || echo "$DIR is empty!"
    

    find 有谓词-empty 用于测试目录或文件是否为空,因此只有在目录为空时才会列出该目录。 -z 测试 find 的输出是否为空。如果是,则目录包含条目,如果不是,则为空。

    换句话说:

    [ -n "$(find "$DIR" -maxdepth 0 -empty)" ] && echo "$DIR is empty!"
    

    另一个相当不错的:

    if ! ls -AU "$DIR" | read _; then
        echo "$DIR is empty!"
    fi
    

    【讨论】:

    • 一些解释会很好
    【解决方案4】:

    您可以为此使用ls -A

    if [ "$(ls -A "$DIR" 2> /dev/null)" == "" ]; then
        # The directory is empty
    fi
    

    -A 显示除了始终存在的... 之外的所有隐藏文件和目录,因此它在空目录中为空白,在包含任何文件或子目录的目录中为非空白。

    2> /dev/null 丢弃ls 可能打印的任何错误消息(请注意,检查不存在的目录会产生误报,但您说您已经检查过它存在)。检查您没有读取权限的目录也会产生误报。

    【讨论】:

    • 如果目录包含大量(长名称)条目,这可能是不利的。此外,“$DIR”需要引号。考虑到这一点 - ... [ "$(ls -A "$DIR" 2>/dev/null | head -n 1)" == "" ] ...
    • @Zrin:在没有任何转义或任何转义的情况下将引号放在引号中感觉很奇怪,但我测试了它,你是绝对正确的(至少,我用带空格的目录名的测试失败了使用我的原件并使用您的更改)。谢谢!不过,| head -n 1 真的有什么帮助吗? ls 仍然会生成完整列表,不是吗?
    • @t-j-crowder | head -n 1 将从ls 中取出第一行,输出它然后切断输入 - 即它说“这就够了!”还有一个很好的解决方案,用read 代替head - 试试| read 并检查退出代码。
    • @Zrin:我知道head 做了什么。但它在这里实现了什么?不管怎样,ls 仍将完成读取大量姓名的所有工作。
    • 你说得对,ls -A 会将整个目录读入内存并在输出第一行之前对其进行排序。通过head 进行管道传输的优点是 bash 不需要读取所有内容(例如考虑大型邮件目录)。缺点是它正在启动另一个进程。也许ls -AU 会立即开始输出?也许if ! ls -AU | read _; then echo 'it's empty'; fi
    【解决方案5】:

    为什么不使用 ls -v ?所以如果没有诸如

    之类的文件,则打印为空
    if $(ls -v $DIR)
    

    【讨论】:

    • 为什么是-v(“文本中自然排序的(版本)数字”)?速度?
    • 另外,这不会检查隐藏文件。
    • 如果目录不为空,会报错。如果你这样做 if ls -v $DIR 没有错误,但它总是正确的。你必须做if [ "$(ls -v "$DIR")" ]if [[ $(ls -v "$DIR") ]]。如果需要,使用! 反转逻辑。
    【解决方案6】:

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

    directory="/path/tmp"
    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
    

    【讨论】:

      【解决方案7】:

      要做到这一点,只使用 shell 内置函数(它应该适用于我使用过的所有 shell):

      if test "`echo /tmp/testdir/* /tmp/testdir/.?*`" = \
          "/tmp/testdir/* /tmp/testdir/.."; then
        [...]
      fi
      

      我们不检查 /tmp/testdir/.*,因为它会扩展到 /tmp/testdir/。 /tmp/testdir/.. 为空文件夹。

      另一个仅内置的变体:

      for i in /tmp/testdir/* /tmp/testdir/.?*; do
          test -e $i || break
          [...]
          break
      done
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2016-05-14
        • 2020-02-03
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多