tar及其关键字母:是bug还是功能?


18

我想问一下这两个命令的区别(即只有它们的选项顺序不同):

  1. tar -zxvf foo.tar.gz
  2. tar -zfxv foo.tar.gz

第一个运行得很好,但是第二个说:

tar: You must specify one of the `-Acdtrux' or `--test-label'  options
Try `tar --help' or `tar --usage' for more information.

而焦油--test-label-zfxv说:

tar (child): xv: Cannot open: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

然后我看了看tar手册,意识到所有示例最终都在使用switch -f!!

AFAICT不需要此限制,还是存在?因为在我看来,开关应该是免费的。


2
@schily您对命令行的“更正”掩盖了他实际键入的命令。前导破折号更改了GNU tar的行为,以使用其他参数解析器。不使用破折号(因此不使用传统的参数解析器),第二个命令将起作用。
Random832

Web系统的增量打印输出告诉我您或其他人在添加-之前,因此我再次将其删除以匹配系统告诉我的是OP中的内容。但是,如果您使用正确gtar option parsing,则会发现不使用gtar的另一个原因。
schily

1
-f要求跟随文件名。在第二个版本中,您指定了-fxv,对于tar而言,它表示文件名是“ xv”。
罗尔夫(Rolf)

Answers:


11

查看您的错误消息,很明显您没有使用tar而是使用了gtar

通常,这可能有助于理解以下内容:

  • tar通常总是需要一个文件参数。如果丢失,它将从系统的默认真实磁带设备读取/写入。star1982年将其更改为默认情况下使用stdin / stdout,最近,此示例遵循了其他一些tar实现(例如gtar)。

  • tar不会实现在tar命令-中调用的选项的前导key letters-为了用户的方便起见,一些实现后来被添加为无操作键字母,但是您不能依靠它。

  • 该方法tar解析其参数(特别是档案文件的说法)是高风险。我已经看到许多tar归档文件破坏了应该在归档文件中的文件之一,因为相关的文件参数被当作tar归档文件。star因为这个原因(好象叫本地的star),不允许使用“f”与其他选项进行级联。如果star调用,tar则会实现与的命令行兼容性tar,但仍会以不同的方式处理“ f”键字母的参数:仅当参数引用的是实际设备文件或(在写入模式下)该文件尚不存在时,才允许使用该参数。

我建议避免使用危险的原始tar命令行,而应使用随带的现代更安全的命令行语法star

由于的命令行语法有问题tar,因此tar wars在1990年代初就有了所谓的。结果,程序pax(拉丁语为“焦油战争”中的“和平”)得以创建和标准化。pax但是,由于它的语法比tar语法风险小,而且直观性差,因此没有得到普及。另一个问题可能是gpax或多或少得不到维护。


3
焦油战争已经结束。高达赢了。
约书亚

2
如果您是对的,为什么所有tar实现都从中复制功能star
2015年

1
顺便说一句:焦油战争是tar和之间的一场战斗cpio
schily

2
OK,这样看来star-f"$file"也是(除ind)与文件名开头的问题=。因此,需要编写-f="$file"-f "$file"。我不确定我会称您的星级选项解析更安全现代
斯特凡Chazelas

3
-long样式长选项与压缩-xyz短选项或不兼容-xarg。这就是为什么X11样式的长选项要求短选项必须分开(-x -y,不是-xy),而选项参数要放在单独的参数中(xterm -n foo,不是xterm -nfoo)。这就是为什么在GNU长选项中有一个额外的破折号,以消除短选项可能造成的混淆,以及为什么GNU风格的长选项是一个更好的设计。仅当您非常小心地避免重叠时,您才可以-foo与之共存-x -y -xy
斯特凡Chazelas

55

切换顺序是免费的,但-f具有必填参数,该参数是tar将读取/写入的文件。

你可以做

tar -zf foo.tar.gz -xv

这样就可以了,并且您对开关的非特定顺序有要求。

这就是所有带有带有参数选项的命令的工作方式。


5
Tar不能像其他命令那样工作,因为它使用了一个更旧的命令行解析器-与“ ar”命令和旧的(POSIX之前的)“ ps”命令所使用的解析器相同。
schily 2015年

1
谢谢您,选择的答案虽然详尽,但并没有真正让我知道问题出在哪里。回想起来,从错误消息中可以明显看出,tar正在尝试读取文件“ xv”
Josh Rumbut

1
我相信您也可以将其声明为-f=./myfile,也就是说,f取一个值,它不是一个标志,而是一个输入。
ThorSummoner

14

传统上,焦油的选项或多或少的“无阶”(在顺序fb如果两者都指定选项事做)。但是,使用前导破折号会导致GNU tar以与其他命令更一致的方式来解析选项,其中指定需要参数的选项(例如的文件名f)将立即消耗其余的“单词”,如果有的话作为参数(传统上,当指定或时,tar使用下一个单词作为文件名/块大小)。在您的情况下,将“ xv”作为文件名。fb

但是,不能依靠此行为来实现可移植性。为了获得最大的可移植性,您应该避免使用破折号,始终放在f最后,f并在文件名和文件名之间始终留一个空格。但是,这是一种简化,如果您需要该b选项,或者通常需要Cf参数之外的任何其他选项(例如),则这种简化会失败。

Tar手册的“三种选项样式”部分对此进行了说明。其他一些实现(例如FreeBSD)将旧样式选项称为“捆绑选项字”。当然,某些实现可能支持这种类型的选项,并且如果包含破折号,则可能会也可能不会忽略。这是Single Unix Specification中指定的唯一调用形式,因此可以保证在几乎所有系统上都可以使用。


2
请注意,某些实现支持带有参数的其他选项(例如C在BSD或GNU tar中。schily tar将其支持为-C,但不支持为C,所有都将其支持为-C)。
斯特凡Chazelas

0

在tar中,开关中的-已在多年前被弃用,不再需要。实际上,Tar曾经告诉过您,但现在不再这样做了。

ie:
tar zxvf foo.tar.gz
tar zfxv foo.tar.gz

Both of these work fine without the -.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.