Regular-Expression
當模式以“/”結尾時,GNU tar 的“轉換”選項行為不一致
tar
在使用--transform
轉換路徑元素的選項時,我遇到了 GNU 的以下奇怪行為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 。
正如@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
緊跟 a/
)。替換文本中的反向引用\1
將確保/
在轉換目錄內文件的路徑名時不會省略。