检查返回结果的最佳方法是什么?

检查返回结果的最佳方法是什么?

我在 shell 脚本中设置了一个函数,用于检查文件夹是否存在,如果不存在,则尝试创建它,如果无法创建文件夹(例如,如果用户没有正确的权限),则返回 1然后我检查这个“return”,但我不明白为什么“if”不起作用,因为return等于1。

代码:

#!/bin/bash
# Main folders
INPUT="input"
OUTPUT="output"

# Functions

function checkFolderExist(){
    if [ -d $1 ]
    then
        # 0 = true
        # Change to 0, only for tests.
        return 1
    else
        mkdir $1
        result=$?
        if [ result==0 ]
        then
            # 0 = true
            return 0
        else
            # 1 = false
            return 1
        fi
    fi
}


CHECKINPUT=$(checkFolderExist $INPUT)
echo $?
CHECKOUTPUT=$(checkFolderExist $OUTPUT)
echo $?

# If folders does not exist, exit the script
if [[ "$CHECKINPUT" = 1 || "$CHECKOUTPUT" = 1 ]]; then
    echo "[+] Error. Folder does not exist. Check user permissions."
    exit 1
fi

答案1

这里有一些事情。

  • 很少必须显式检查$?任何内容或将其保存在变量中(除非您需要多次引用相同的退出状态)。
  • 函数的退出状态是函数中最后执行的命令的退出状态,因此return很少需要显式退出(很少带有显式返回)价值至少)。
  • 检查目录是否存在的函数不应创建任何目录。最好叫它create_dir_if_needed
  • 中有一个错误[ result==0 ]。该字符串result==0是一个非零长度的字符串,用这种方式测试字符串将返回真的如果字符串的长度非零,则测试始终为真。你可能想要的[ "$result" -eq 0 ]是。
  • 请记住始终使用双引号变量扩展和命令替换,除非您知道在什么上下文中这不是必需的

考虑到这些事情:

create_dir_if_needed () {
    mkdir -p -- "$1"
}

这将返回 的退出状态mkdir -p -- "$1"。如果指定目录(以及任何中间目录)尚不存在,则此命令将创建该目录。如果mkdir命令创建目录失败,它将以非零退出状态退出,该退出状态将成为函数的退出状态。 mkdir -p如果目录已经存在则不会失败。

你可以用它作为

if ! create_dir_if_needed "$dirpath"; then
    printf 'Failed to create directory "%s"\n' "$dirpath" >&2
    exit 1
fi

或者,由于该功能很简单,您可以摆脱它并说

if ! mkdir -p -- "$dirpath"; then
    printf 'Failed to create directory "%s"\n' "$dirpath" >&2
    exit 1
fi

该函数的一个变体create_dir_if_needed使用mkdirwithout -p,因此永远不会为给定的目录路径创建丢失的父目录:

create_dir_if_needed () {
    if [ -d "$1" ]; then
        return
    fi

    mkdir -- "$1"
}

或者,

create_dir_if_needed () {
    [ -d "$1" ] || mkdir -- "$1"
}

调用此函数将返回真的(零)如果目录已经存在或者调用mkdir顺利。没有显式值的语句return将返回最近执行的语句的退出状态,在这种情况下,它将返回测试的肯定结果[ -d "$1" ]

答案2

在返回值方面,Bash 与常规编程语言不同。

这里你很困惑输出来自 checkFolderExist 与返回状态来自 checkFolderExist。

您的 CHECKINPUT 和 CHECKOUTPUT 变量将为空,因为您的函数什么echo也没有printf

如果你真的想保存你的函数返回状态为了以后使用,你应该这样做:

checkFolderExist "${INPUT}"
CHECKINPUT=$?

checkFolderExist "${OUTPUT}"
CHECKOUTPUT=$?

除此之外,无论如何我建议您遵循以下建议拘萨罗南达的回答指导您采用更好的技术来解决问题。

答案3

您混淆了函数的输出与返回值。我向您展示了最少的工作示例,以便您可以看到您的错误:

要么返回:

myfunc() {
  return 1
}

myfunc
ret=$?
[ $ret -eq 0 ] && echo OK

或写入标准输出并检查输出:

myfunc() {
  echo '1'
}

ret="$(myfunc)"
[ "$ret" = '0' ] && echo OK

另请注意,我更喜欢区分变量的整数和字符串ret,如果您知道输出只能是数字但使其更清晰,则实际上没有必要。此外,如果条件语句紧随其后,则无需将返回值捕获到变量中。

这是您想要的第一个,因此您不能使用$().您确实将它们混合在一起:如第一个示例中那样返回值,并如第二个示例中那样检查输出。

相关内容