Regular-Expression

當模式以“/”結尾時,GNU tar 的“轉換”選項行為不一致

  • October 18, 2021

tar在使用--transform轉換路徑元素的選項時,遇到了 GNU 的以下奇怪行為tar:當轉換模式明確包含./

重現:

  • 創建一個test-dir包含虛擬內容的目錄:
$ mkdir test-dir
$ touch test-dir/test{1..50}.txt
  • tar此目錄重命名為test-dir/to transformed-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將確保/在轉換目錄內文件的路徑名時不會省略。

引用自:https://unix.stackexchange.com/questions/629834