我有一个将写入输出文件的bash程序。此文件可能存在也可能不存在,但脚本必须检查权限并尽早失败。我无法找到一种优雅的方式来实现这一目标。这是我尝试过的。
set +e touch $file set -e if [ $? -ne 0 ]; then exit;fi
我为此脚本保留set -e
,以便在任何行上出现错误时失败。是否有更简单的方法来执行上述脚本?
答案 0 :(得分:31)
为什么复杂化?
file=exists_and_writeable
if [ ! -e "$file" ] ; then
touch "$file"
fi
if [ ! -w "$file" ] ; then
echo cannot write to $file
exit 1
fi
或者,更简洁,
( [ -e "$file" ] || touch "$file" ) && [ ! -w "$file" ] && echo cannot write to $file && exit 1
答案 1 :(得分:22)
不要在另一行上检查$?
,而是立即检查返回值:
touch file || exit
只要您的umask
不限制写位,您就可以依赖touch
的返回值
答案 2 :(得分:3)
您可以使用-w
检查文件是否可写(在bash手册页中搜索)。
if [[ ! -w $file ]]; then exit; fi
答案 3 :(得分:3)
为什么脚本必须尽早失败?通过将可写测试和文件open()分开,可以引入竞争条件。相反,为什么不尝试打开(截断/追加)文件进行写入,如果发生错误则处理错误?类似的东西:
$ echo foo > output.txt
$ if [ $? -ne 0 ]; then die("Couldn't echo foo")
正如其他人所说,如果你想避免覆盖现有文件,“noclobber”选项可能会有用。
答案 4 :(得分:2)
打开文件进行写作。在shell中,这是通过输出重定向完成的。您可以通过将重定向放在exec
内置而没有参数的情况下重定向shell的标准输出。
set -e
exec >shell.out # exit if shell.out can't be opened
echo "This will appear in shell.out"
确保您没有设置noclobber
选项(这在交互式中非常有用,但在脚本中通常无法使用)。如果要截断文件(如果存在),请使用>
;如果要添加文件,请使用>>
。
如果您只想测试权限,可以运行: >foo.out
来创建文件(如果存在则截断文件)。
如果您只想要一些命令写入文件,请在其他描述符上打开它,然后根据需要重定向。
set -e
exec 3>foo.out
echo "This will appear on the standard output"
echo >&3 "This will appear in foo.out"
echo "This will appear both on standard output and in foo.out" | tee /dev/fd/3
(/dev/fd
在任何地方都不受支持;它至少在Linux,* BSD,Solaris和Cygwin上可用。)