Bash:如果文件不存在则创建一个文件,否则检查它是否可写

时间:2010-12-22 16:39:25

标签: linux bash

我有一个将写入输出文件的bash程序。此文件可能存在也可能不存在,但脚本必须检查权限并尽早失败。我无法找到一种优雅的方式来实现这一目标。这是我尝试过的。

set +e
touch $file
set -e

if [ $? -ne 0 ]; then exit;fi

我为此脚本保留set -e,以便在任何行上出现错误时失败。是否有更简单的方法来执行上述脚本?

5 个答案:

答案 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上可用。)