将文件扩展名与数组中允许的一组扩展名匹配

时间:2019-04-25 03:08:55

标签: bash shell

在此功能中,将处理文件目录。该目录应仅包含EXT数组中指定/配置的内容。该函数的目的是检查该目录是否存在不允许的扩展名,即在运行该函数时是否仅在EXT数组中配置了.mp3.png它检测到.gif文件,并引发错误。我的代码在技术上可以像现在这样正常工作,但是问题是,遍历扩展时它总是失败。

# USER VARIABLES
INPUT=/home/administrator/music/v1.1/input
OUTPUT=/home/administrator/music/v1.1/output
declare -a EXT
EXT[0]=".png"
EXT[1]=".mp3"

function CHECK_EXT()
{
        for FULLPATH in $INPUT/*; do
                FULLNAME=$(basename -- "$FULLPATH")
                i=0
                for i in "${!EXT[@]}"; do
                        EXT="${EXT[$i]}"
                        if [[ $FULLNAME != *"$EXT" ]]; then
                                ERROR="Unsupported file type detected!"
                                return 0
                        fi
                done
        done
        return 1
}

3 个答案:

答案 0 :(得分:2)

您可以重新编写逻辑以检查扩展部分,如下所示。这个想法是生成一个字符串,用于与所有可能的扩展名(即

)进行备用匹配
declare -A ext
ext[0]="png"
ext[1]="mp3"

现在生成包含可能的扩展名匹配项的字符串,并使用printf -v语法将其存储在变量中,该语法将格式化后的字符串存储在变量中。

printf -v globStr '!(%s)' "$(IFS="|"; printf '%s' "${ext[*]}")"

现在使用bash extglob语法的thr !(opt1|opt2)模式匹配以下文件名扩展名。请注意,我们从数组扩展中删除了.字符。 ${filename##*.}语法删除文件名的一部分,仅保留扩展名。

if [[ ${filename##*.} == $globStr ]]; then
    printf '%s\n' "Only ${ext[*]} files are supported"
fi

将所有内容放在一起

#!/usr/bin/env bash
#              ^^^^ needed for [[ operator to work, not POSIX compliant

input=/home/administrator/music/v1.1/input
output=/home/administrator/music/v1.1/output

declare -A ext
ext[0]="png"
ext[1]="mp3"

# The array expansion of type "${arr[*]}" generates a single string
# with the array contents based on the IFS value set. For alternate
# match we define a custom IFS value inside "$(..)" as the value 
# defined inside it is not reflected outside.

printf -v globStr '!(%s)' "$(IFS="|"; printf '%s' "${ext[*]}")"

for file in "$input"/*; do
    [ -f "$file" ] || continue
    filename=$(basename -- "$file")

    # The '==' inside the '[[..]]' enables the extglob option
    # using which we match the set of not allowed filename extensions

    if [[ ${filename##*.} == $globStr ]]; then
        printf '%s\n' "Only ${ext[*]} files are supported - got $filename"
    fi
done

请注意,对于用户定义的变量,请使用小写的变量名。这样做总是 的好习惯,因为大写名称保留供外壳使用。

答案 1 :(得分:0)

您的问题在这里:

EXT="${EXT[$i]}"

您每次运行都会覆盖EXT数组内容。同样,除了循环遍历数组索引之外,还可以这样编写循环块:

for FULLPATH in $INPUT/*; do
  # check whether the file extension is NOT in the allowed EXT array
  if [[ ! " ${EXT[@]} " =~ "$(basename -- "$FULLPATH")" ]]; then
    ERROR="Unsupported file type detected!"
    return 1
  fi
done

答案 2 :(得分:0)

仅解决您所要求的测试,这就是您需要做的所有事情:

# USER VARIABLES
INPUT=/home/administrator/music/v1.1/input
OUTPUT=/home/administrator/music/v1.1/output
declare -A EXT
EXT[".png"]=1
EXT[".mp3"]=1

function CHECK_EXT()
{
        for FULLPATH in $INPUT/*; do
            if (( "${EXT[${FULLPATH##*.}]}" != 1 )); then
                ERROR="Unsupported file type detected!"
                return 0
            fi
        done
        return 1
}

还有其他方法可以改进脚本,例如小写变量,局部变量声明,带引号的变量,标准成功/失败返回值和shebang。未经测试,这更接近您应如何真正编写它:

#!/usr/bin/env bash
# USER VARIABLES
input_dir='/home/administrator/music/v1.1/input'
output_dir='/home/administrator/music/v1.1/output'
declare -A exts
exts[".png"]=1
exts[".mp3"]=1

function check_exts() {
    local input_dir="$1" full_path ext
    for full_path in "$input_dir"/*; do
        ext="${full_path##*.}"
        if (( "${exts[$ext]}" != 1 )); then
            error='Unsupported file extension "'"$ext"'" detected!'
            return 1
        fi
    done
    return 0
}

check_exts "$input_dir" || { printf 'Failed\n' >&2; exit 1; }

idk变量error真正如何在您的真实代码中起作用。