调用命令
检查返回值
始终检查返回值并给出有意义的返回值。
对于非管道命令,使用 $? 或通过 if 语句直接检查以保持简单。
示例:
if ! mv "${file_list[@]}" "${dest_dir}/"; then
echo "Unable to move ${file_list[*]} to ${dest_dir}" >&2
exit 1
fi
# Or
mv "${file_list[@]}" "${dest_dir}/"
if (( $? != 0 )); then
echo "Unable to move ${file_list[*]} to ${dest_dir}" >&2
exit 1
fiBash 还有 PIPESTATUS 变量,允许检查管道中所有部分的返回码。
如果只需要检查整个管道的成功或失败,则以下方式是可以接受的:
tar -cf - ./* | ( cd "${dir}" && tar -xf - )
if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
echo "Unable to tar files to ${dir}" >&2
fi但是,由于 PIPESTATUS 会在你执行任何其他命令后立即被覆盖,
如果你需要根据管道中错误发生的位置采取不同的操作,
你需要在运行命令后立即将 PIPESTATUS 赋值给另一个变量
(不要忘记 [ 是一个命令,会清除 PIPESTATUS)。
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
return_codes=( "${PIPESTATUS[@]}" )
if (( return_codes[0] != 0 )); then
do_something
fi
if (( return_codes[1] != 0 )); then
do_something_else
fi内建命令 vs. 外部命令
在调用 Shell 内建命令和调用外部进程之间做选择时,选择内建命令。
我们优先使用内建命令,例如 bash 提供的
参数展开(Parameter Expansion)
功能,因为它更高效、健壮和可移植(特别是与 sed 等工具相比)。
另请参见
=~ 运算符。
示例:
# Prefer this:
addition="$(( X + Y ))"
substitution="${string/#foo/bar}"
if [[ "${string}" =~ foo:(\d+) ]]; then
extraction="${BASH_REMATCH[1]}"
fi# Instead of this:
addition="$(expr "${X}" + "${Y}")"
substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
extraction="$(echo "${string}" | sed -e 's/foo:\([0-9]\)/\1/')"Last updated on