【问题标题】:Bash: Check if a directory contains only files with a specific suffixBash:检查目录是否仅包含具有特定后缀的文件
【发布时间】:2019-08-24 19:09:26
【问题描述】:

我正在尝试编写一个脚本来检查一个目录是否只包含 特定类型的文件(和/或文件夹),将返回 1 为 false,0 为 true。

IE:我想检查 /my/dir/ 是否只包含 *.gz 文件而不包含其他文件。

这是我目前所拥有的,但它似乎没有按预期工作:

# Basic vars
readonly       THIS_JOB=${0##*/}
readonly       ARGS_NBR=1


declare        dir_in=$1


dir_in=$1"/*.gz"
#echo $dir_in

files=$(shopt -s nullglob dotglob; echo ! $dir_in)
echo $files

if (( ${#files} ))
then
    echo "Success: Directory contains files."
    exit 0
else
    echo "Failure: Directory is empty (or does not exist or is a file)"
    exit 1
fi

【问题讨论】:

    标签: bash directory file-exists


    【解决方案1】:

    有些人建议计算所有与通配符模式*.gz 不匹配的文件。根据文件的数量,这可能非常低效。对于您的工作,只需找到一个与您的通配模式不匹配的文件就足够了。使用find-quite 动作在第一场比赛后退出:

    if [ -z "$(find /usr/share/man/man1/* -not -name '*.gz' -print -quit)" ]
    then echo only gz
    fi
    

    【讨论】:

    • 我认为 -not-quit 不符合 POSIX。 -not 可以简单地替换为 !-quitbusybox 中不存在例如。在这种情况下,由于我们有 bash,我想它可以替换为 -exec bash -c 'kill -PIPE $PPID' \;(或只是 find ... | head -n 1
    • @jhnc 一个使用 GNU 工具 Bash 的人,可能也使用其他 GNU 工具,并且不关心 POSIX 合规性。
    • 我在 freebsd 上使用 bash,但许多实用程序不是 GNU
    【解决方案2】:

    由于您使用的是 bash,因此您可以使用另一个设置:GLOBIGNORE

    #!/bin/bash
    
    containsonly(){
        dir="$1"
        glob="$2"
    
        if [ ! -d "$dir" ]; then
            echo 1>&2 "Failure: directory does not exist"
            return 2
        fi
    
        local res=$(
            cd "$dir"
            GLOBIGNORE=$glob"
            shopt -s nullglob dotglob
            echo *
        )
        if [ ${#res} = 0 ]; then
            echo 1>&2 "Success: directory contains no extra files"
            return 0
        else
            echo 1>&2 "Failure: directory contains extra files"
            return 1
        fi
    }
    
    # ...
    
    containsonly myfolder '*.gz'
    
    

    【讨论】:

      【解决方案3】:

      使用 Bash 的 extglob!(*.gz)grep

      $ if grep -qs . path/!(*.gz) ; then echo yes ; else echo nope ; fi
      

      man grep:

      -q, --quiet, --silent
             Quiet;  do  not  write  anything  to  standard   output.    Exit
             immediately  with  zero status if any match is found, even if an
             error was detected.  Also see the -s or --no-messages option.
      
      -s, --no-messages
             Suppress error messages about nonexistent or unreadable files.
      

      【讨论】:

        【解决方案4】:

        我想检查 /my/dir/ 是否只包含 *.gz 文件而不包含其他文件。

        使用find 而不是通配符。使用find 和解析查找输出真的更容易。 Globulation 对于简单脚本来说很简单,但是一旦你想解析“目录中的所有文件”并进行一些过滤等,使用find 会更容易(也更安全):

        find "$1" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f | wc -l | xargs test 0 -eq
        

        这会在目录中找到所有未命名为 *.gz 或不是文件的“事物”(因此考虑了 mkdir a.gz),对它们进行计数,然后测试它们的计数是否等于 0。如果计数等于 0,xargs test 0 -eq 将返回 0,否则将返回 1 - 125 之间的状态。如果您愿意,可以使用简单的|| return 1 处理非零返回状态。

        您可以通过简单的 bash 替换删除 xargs,并使用 this thread 中的方法稍微加快速度并获得 test 返回值,即 01

        [ 0 -eq "$(find "$1" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f -print '.' | wc -c)" ]
        

        请记住,脚本的退出状态是最后执行的命令的退出状态。因此,如果您愿意,您的脚本中不需要任何其他内容,只需一个 shebang 和这个 oneliner 就足够了。

        【讨论】:

        • 不确定你能保证 xargs 会返回 123(freebsd 返回 1),但肯定应该是 1..125 之间的值
        猜你喜欢
        • 2023-03-27
        • 2016-01-28
        • 1970-01-01
        • 1970-01-01
        • 2011-05-04
        • 1970-01-01
        • 2014-12-23
        • 2014-05-10
        • 2017-04-28
        相关资源
        最近更新 更多