如何防止 tar 创建空存档?

How can I prevent tar from creating an empty archive?

/tmp/-> ls ab*
/tmp/-> ls: ab*: No such file or directory

/tmp/-> tar -cvf ab.tar abc*
tar: abc*: Cannot stat: No such file or directory
tar: Error exit delayed from previous errors
/tmp/->
/tmp/-> ls ab*
ab.tar
/tmp/-> tar -tvf ab.tar
/tmp/->

可以看出,没有与模式 abc* 匹配的文件,但是创建的名为 ab.tar 的输出文件没有内容。是否有 switch/option 可以传递给 tar 命令,以便在没有输入文件时不创建输出文件?

Is there a switch/option than can be passed to tar command so that no output file is created when there are no input file?

Gnu tar 没有这样的选项.

这里有两种选择。你需要研究它们并弄清楚什么对你有用,因为它们有点像 hack。

你可以这样做:

Tar,测试,为空时去掉

tar -cvf ab.tar abc* ||
    tar tf ab.tar | read ||
        rm ab.tar

解释:

如果tar -cvf ...失败,用tar tf ...获取内容。

如果read失败,则存档为空,保存并删除它。


或者您可以尝试:

测试,然后tar

ls abc* | read && tar -cvf ab.tar abc*

这首先不会创建空的 tar 文件。

有一种方法可以让 shell 做到这一点:

#!/bin/sh
# safetar -- execute tar safely

sh -O failglob -c 'tar cvf ab.tar abc*'

我喜欢在这种情况下使用 for-as-if 构造:

for x in abc*; do
    # exit the loop if no file matching abc* exists
    test -e "$x" || break
    # by now we know at least one exists (first loop iteration)
    tar -cvf ab.tar abc*
    # and since we now did the deed already… exit the “loop”
    break
done

“循环”的主体 运行 正好通过一次,但 shell 为我们完成了 globbing。 (我通常使用 continue 代替第一个 break,但可能不需要。)

或者,您可以使用 shell 将 glob 扩展为 $*

set -- abc*
test -e "" && tar -cvf ab.tar abc*

如果您的脚本 运行 在 set -e 下,请改用 if test …; then tar …; fi,否则当文件不存在时它将中止。

所有这些变体也可以在普通 中使用。