bash - 如果失败,在 Bash 中执行一行而不中止?

标签 bash

在 bash 脚本中是否有一种通用的方法来“尝试”某事但如果失败则继续?其他语言中的类似方法是将其包装在 try/catch 中并忽略异常。

具体来说,我正在尝试获取一个可选的卫星脚本文件:

. $OPTIONAL_PATH

但是当执行这个时,如果 $OPTIONAL_PATH 不存在,整个脚本就会停止。

我知道我可以在获取文件之前检查它是否存在,但我很好奇是否有一个通用的可重用机制我可以使用它来忽略错误而不停止。

更新:显然这不是正常行为。我不确定为什么会这样。我没有在任何地方明确调用 set -e($-hB),但它会因错误而停止。这是我看到的输出:

./script.sh: line 36: projects/mobile.sh: No such file or directory

我在源代码行之后立即添加了一个 echo "test",但它从不打印,所以在该行之后没有任何内容正在退出。我运行的是 Mac OS 10.9。

更新 2:没关系,它确实被标记为 #!/bin/sh 而不是 #!/bin/bash。感谢 Kaz 提供的信息丰富的答案。

最佳答案

失败的命令不会中止脚本,除非您使用 set -e 显式配置该模式。

关于 Bash 的点命令,事情很棘手。如果我们将 bash 作为 /bin/sh 调用,那么如果 . 命令没有找到该文件,它就会退出脚本。如果我们将 bash 调用为 /bin/bash 那么它就不会失败!

$ cat source.sh 
#!/bin/sh

. nonexistent
echo here
$ ./source.sh 
./source.sh: 3: .: nonexistent: not found
$ ed source.sh 
35
1s/sh/bash/
wq
37
$ ./source.sh 
./source.sh: line 3: nonexistent: No such file or directory
here

它确实响应set -e;如果我们有 #!/bin/bash,并使用 set -e,则 echo 不会到达。因此,一种解决方案是以这种方式调用 bash。

如果你想保持脚本最大的可移植性,看来你必须做测试。

点命令中止脚本的行为是 POSIX 所要求的。搜索“点”关键字 here .引用:

如果找不到可读文件,非交互式 shell 将中止;交互式 shell 应将诊断消息写入标准错误,但这种情况不应被视为语法错误。

可以说,这是正确的做法,因为点用于包含脚本片段。当整个脚本 block 都没有找到时,脚本如何继续?

否则可以说,这是与其他命令的处理不一致的脑损伤行为,因此 Bash 使其在其不符合 POSIX 的模式下保持一致。如果程序员希望命令失败,他们可以使用 set -e

我倾向于同意 Bash。 POSIX 行为实际上比最初看起来更糟糕,因为这也不是您想要的方式:

if . nonexistent ; then
  echo loaded
fi

即使命令经过测试,它仍然会在退出时中止脚本。

感谢 GNU-deness,我们有替代实用程序和源代码。

关于bash - 如果失败,在 Bash 中执行一行而不中止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20104989/

相关文章:

python - 从 python 脚本更改目录 : how to not open a new shell

linux - 将 cron 日志存储在 timedate 文件中

bash - 正则表达式解析字符串以提取shell脚本中的数字

linux - bash 脚本 : ssh create file; sleep 3m; rm file;

bash - sed:用文件内容替换一系列文本

linux - 如何以 320KiB 倍数分割文件

Git-commit 无法打开 vim

linux - 当命令使用 EOF 变量时删除 BASH 中命令的输出

linux - bash read 返回退出代码 1,即使它按预期运行

linux - -x 和 -c 字符串比较选项有什么作用?