通常我们可以将命令输出重定向到文件,如下所示:
cat a.txt >> output.txt
我尝试过,如果cat
失败,仍会创建output.txt
,这不是我预期的。我知道我可以这样测试:
if [ "$?" -ne "0"]; then
rm output.txt
fi
但是,在output.txt
执行之前已经有cat
这样的问题,这可能会导致一些问题。
所以我还需要在output.txt
之前存储cat
状态,如果在cat
执行之前已经有这样的output.txt,我不应该错误地output.txt
。 ..但是在竞争条件下可能仍然存在问题,如果任何其他进程在我的cat
之前非常接近地创建了这个output.txt怎么办?
有没有简单的方法,如果命令失败,重定向output.txt将被删除,甚至不会被创建?
答案 0 :(得分:3)
修正输出文件名是坏消息;不要使用它们。
您应该重新设计处理,以便有一个带有日期戳的文件名。如果不这样做,你应该使用mktemp
命令创建一个临时文件,让你想要执行的命令写入该命令,当命令成功时,你可以将临时文件移动到'final'输出 - 然后你可以在故障时自动清理临时。
outfile="./output-$(date +%Y-%m-%d.%H:%M:%S).txt"
tmpfile="$(mktemp ./gadget-maker.XXXXXXXX)"
trap "rm -f '$tmpfile'; exit 1" 0 1 2 3 13 15
if cat a.txt > "$tmpfile"
then mv "$tmpfile" "$outfile"
else rm "$tmpfile"
fi
trap 0
如果您坚持(但不安全),您可以将outfile
简化为output.txt
。您可以使用mktemp
命令使用任何您喜欢的前缀。请注意,通过在当前目录中创建临时文件(也将创建最终输出文件),可以避免在mv
操作阶段复制跨设备文件 - 它是link()
和unlink()
系统调用(或者甚至是rename()
系统调用,如果你的机器上存在这样的东西;它只在Mac OS X上运行)。
答案 1 :(得分:0)
我认为这样可行,请查看。
[ -e output.txt ] && (mv output.txt output.txt_bkp)
cat a.txt > /dev/null 2>&1;[ $? -eq 0 ] && (cat a.txt > output.txt)
乔纳森建议的另一种方式,
[ -e output.txt ] && (mv output.txt output.txt_bkp)
if cat a.txt > /dev/null 2>&1
then
cat a.txt > output.txt
fi
答案 2 :(得分:0)
在命令终止之前,您无法判断命令是否已失败,到那时它可能会产生一些输出。
可能更有用的条件是避免在命令实际产生一些输出之前创建输出文件,而不用担心它的状态代码。
这很接近:
command | { IFS= read -rn1 -d '' a &&
{ printf %s "$a" >> output.txt
cat >> output.txt
}
}
但是,如果command
输出的第一个字符是NUL字节,则NUL不会被写入输出文件。由于输出文件的扩展名为.txt
,因此在这种特殊情况下不太可能,但可以通过添加命令来处理
[[ -z $a ]] && printf '\0' >> output.txt
在printf之后和猫之前。