![当模式以“/”结尾时,GNU tar 的“转换”选项表现不一致](https://linux22.com/image/186641/%E5%BD%93%E6%A8%A1%E5%BC%8F%E4%BB%A5%E2%80%9C%2F%E2%80%9D%E7%BB%93%E5%B0%BE%E6%97%B6%EF%BC%8CGNU%20tar%20%E7%9A%84%E2%80%9C%E8%BD%AC%E6%8D%A2%E2%80%9D%E9%80%89%E9%A1%B9%E8%A1%A8%E7%8E%B0%E4%B8%8D%E4%B8%80%E8%87%B4.png)
tar
当我使用转换路径元素的选项时,我遇到了 GNU 的以下奇怪行为--transform
:当我尝试tar
整个子目录并想要转换到该目录的路径时,转换是不是当转换模式明确包含时,它不仅应用于目录本身,还应用于其内容/
。
重现:
- 创建一个包含虚拟内容的目录
test-dir
:$ mkdir test-dir $ touch test-dir/test{1..50}.txt
tar
该目录重命名为test-dir/
totransformed-dir/
,并指示tar
打印转换后的名称以进行检查:$ tar --transform="s,^test-dir/,transformed-dir/," --show-transformed-names -cvf test.tar test-dir test-dir/ transformed-dir/test25.txt transformed-dir/test29.txt transformed-dir/test47.txt ...
如您所见,目录本身是不是尽管重命名适用于目录中的所有文件,但已正确重命名。
- 为了进行比较,使用相同的转换,但是没有尾随
/
:$ tar --transform="s,^test-dir,transformed-dir," --show-transformed-names -cvf test2.tar test-dir transformed-dir/ transformed-dir/test25.txt transformed-dir/test29.txt transformed-dir/test47.txt ...
现在,目录本身是正确重命名。
当省略锚点时,该行为不会改变,并且与是否在命令行中^
指定要压缩的目录无关。/
- 我想知道问题是否是当
/
指定时,在目录的情况下全部的文件名可能会被替换。但是,当指定将重命名整个文件的转换时,它可以正常工作:$ tar --transform="s,^test-dir/test29.txt,transformed-dir/file.txt," --show-transformed-names -cvf test3.tar test-dir test-dir/ test-dir/test25.txt transformed-dir/file.txt test-dir/test47.txt ...
所以看来尾随确实/
是问题所在。这是一个功能、一个错误,还是我以某种方式误解了该选项的范围/语法?版本tar
是 GNU tar 1.28。
答案1
正如 @muru 和 @UncleBilly 的评论所指出的,这里的问题可能是 GNU 的误解和不幸的输出的混合体tar
。
- 当以“详细”模式 (
-v
) 运行时,(GNU)将在所有引用目录而不是文件的条目后tar
附加尾随。/
- 然而,这
/
当然是不是实际目录名称的一部分存储在文件系统数据中。 - 该转换似乎适用于目录条目的“实际”名称,其中才不是匹配模式,因为不是名称的一部分。
some_name/
/
因此,该选项看似不一致的行为--transform
是由于打印目录名称与实际(和内部使用)目录名称。
正如@UncleBilly 所指出的,如果你想确保只有完全匹配指定名称的目录才应该被重命名,像这样的转换语句
--transform='s,^path/to/dir\($\|/\),newname\1,'
将确保仅重命名目录path/to/dir
(应用字符串结尾锚点的位置$
)及其内容path/to/dir/fileXXX.yyy
(dir
紧随其后的位置/
)。\1
替换文本中的反向引用将确保/
在转换目录内文件的路径名时不会省略 。