目錄

名稱

Archive::Tar - 處理 tar 檔案的模組

概要

use Archive::Tar;
my $tar = Archive::Tar->new;

$tar->read('origin.tgz');
$tar->extract();

$tar->add_files('file/foo.pl', 'docs/README');
$tar->add_data('file/baz.txt', 'This is the contents now');

$tar->rename('oldname', 'new/file/name');
$tar->chown('/', 'root');
$tar->chown('/', 'root:root');
$tar->chmod('/tmp', '1777');

$tar->write('files.tar');                   # plain tar
$tar->write('files.tgz', COMPRESS_GZIP);    # gzip compressed
$tar->write('files.tbz', COMPRESS_BZIP);    # bzip2 compressed
$tar->write('files.txz', COMPRESS_XZ);      # xz compressed

說明

Archive::Tar 提供一個物件導向的機制來處理 tar 檔案。它提供類別方法來快速輕鬆地處理檔案,同時也允許建立 tar 檔案物件進行自訂處理。如果您已安裝 IO::Zlib 模組,Archive::Tar 也將支援壓縮或 gzip 的 tar 檔案。

Archive::Tar 類別的物件表示一個充滿檔案和事物的 .tar(.gz) 檔案。

物件方法

Archive::Tar->new( [$file, $compressed] )

傳回一個新的 Tar 物件。如果給予任何引數,new() 會自動呼叫 read() 方法,將提供的引數傳遞給 read() 方法。

如果 new() 呼叫時帶有引數,而 read() 方法因任何原因失敗,new() 會傳回未定義值。

$tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )

將指定的 tar 檔案讀取至記憶體。第一個引數可以是檔案名稱或已開啟檔案處理的參考 (或 IO::Zlib 物件,如果已壓縮)

read取代 $tar 中的任何先前內容!

第二個引數可以視為選用,但保留以維持向後相容性。Archive::Tar 現在會查看檔案魔術數字,以判斷應使用哪個類別開啟檔案,並會透明地執行正確的動作。

如果您嘗試傳遞 bzip2 / xz 壓縮檔案,而 IO::Uncompress::Bunzip2 / IO::Uncompress::UnXz 不可用,Archive::Tar 會發出警告,並只會傳回。

請注意,您目前無法傳遞未以 IO::Zlib 開啟的 gzip 壓縮檔案處理、未以 IO::Uncompress::Bunzip2 開啟的 bzip2 壓縮檔案處理、未以 IO::Uncompress::UnXz 開啟的 xz 壓縮檔案處理,或包含完整檔案資訊的字串 (壓縮或未壓縮)。這些都是有價值的功能,但目前尚未實作。請參閱 TODO 區段。

第三個引數可以是包含選項的雜湊參考。請注意,所有選項都區分大小寫。

limit

不要讀取超過 limit 個檔案。如果您有非常大的檔案,而且只對前幾個檔案有興趣,這會很有用。

filter

可以設定為正規表示式。只有名稱符合該表示式的檔案才會被讀取。

md5

設定為 1,則會傳回檔案的 md5sum (而非檔案資料) my $iter = Archive::Tar->iter( $file, 1, {md5 => 1} ); while( my $f = $iter->() ) { print $f->data . "\t" . $f->full_path . $/; }

extract

如果設定為 true,則在讀取項目時立即解壓縮。這會讓您獲得與 extract_archive 函式相同的記憶體中斷。但是,請注意,項目不會讀取至記憶體,而是直接寫入磁碟。這表示不會為您建立 Archive::Tar::File 物件以供您檢查。

所有檔案都以 Archive::Tar::File 物件儲存在內部。請參閱 Archive::Tar::File 文件以取得詳細資訊。

在標量上下文中傳回讀取檔案的數量,以及在清單上下文中傳回 Archive::Tar::File 物件的清單。

$tar->contains_file( $filename )

檢查封存檔是否包含特定檔案。如果封存檔中包含該檔案,則傳回 true,否則傳回 false。

不過,請注意,此函式使用 eq 對完整路徑執行精確比對。因此,它無法補償不區分大小寫的檔案系統,也無法比較 2 個路徑以查看它們是否指向同一個底層檔案。

$tar->extract( [@filenames] )

將名稱等於 @filenames 中任何名稱的檔案寫入磁碟,並視需要建立子目錄。這在 VMS 下可能無法正常運作。在 MacPerl 下,檔案的修改時間將轉換為 MacOS 的時間零,並且會對路徑執行適當的轉換。不過,不會檢查路徑中每個元素的長度是否超過 MacOS 目前允許的長度(32 個字元)。

如果在未提供檔案名稱清單的情況下呼叫 extract,則會萃取封存檔的全部內容。

傳回萃取的檔案名稱清單。

$tar->extract_file( $file, [$extract_path] )

將名稱等於提供的檔案名稱的項目寫入磁碟。選擇性地採用第二個參數,該參數是項目將寫入的完整原生路徑(包括檔案名稱)。

例如

$tar->extract_file( 'name/in/archive', 'name/i/want/to/give/it' );

$tar->extract_file( $at_file_object,   'name/i/want/to/give/it' );

成功時傳回 true,失敗時傳回 false。

$tar->list_files( [\@properties] )

傳回封存檔中所有檔案名稱的清單。

如果 list_files() 將陣列參考作為其第一個引數傳遞,則它會傳回包含每個檔案的請求屬性的雜湊參考清單。支援下列屬性清單:名稱、大小、mtime(上次修改日期)、模式、uid、gid、linkname、uname、gname、devmajor、devminor、prefix。

傳遞只包含一個元素「name」的陣列參考,會特別處理成傳回名稱清單,而不是雜湊參考清單,這等於呼叫沒有參數的 list_files

$tar->get_files( [@filenames] )

傳回與提供的檔名相符的 Archive::Tar::File 物件。如果沒有傳遞檔名清單,則傳回目前 Tar 物件中的所有 Archive::Tar::File 物件。

請參閱 Archive::Tar::File 文件,了解如何處理這些物件。

$tar->get_content( $file )

傳回指定檔案的內容。

$tar->replace_content( $file, $content )

將字串 $content 設定為指定檔案 $file 的內容。

$tar->rename( $file, $new_name )

將記憶體中檔案庫的檔案重新命名為 $new_name。

請注意,您必須為 $new_name 指定 Unix 路徑,因為根據 tar 標準,檔案庫中的所有檔案都必須是 Unix 路徑。

成功傳回 true,失敗傳回 false。

$tar->chmod( $file, $mode )

將 $file 的模式變更為 $mode。

成功傳回 true,失敗傳回 false。

$tar->chown( $file, $uname [, $gname] )

將 $file 的擁有者變更為 $uname 和 $gname。

成功傳回 true,失敗傳回 false。

$tar->remove (@filenamelist)

從內存檔案中移除任何與給定檔名相符的項目。傳回一個剩餘的 Archive::Tar::File 物件清單。

$tar->clear

clear 清除目前的內存檔案。這會有效地提供一個「空白」物件,準備再次填入。請注意,clear 僅對物件產生影響,不會影響底層的 tar 檔案。

$tar->write ( [$file, $compressed, $prefix] )

將內存檔案寫入磁碟。第一個引數可以是檔案名稱或已開啟的檔案處理常式的參考 (一個 GLOB 參考)。

第二個引數用於指示壓縮。您可以使用 gzipbzip2xz 進行壓縮。如果您傳遞一個數字,則假設它是 gzip 壓縮等級 (介於 1 到 9 之間),但建議使用常數

# write a gzip compressed file
$tar->write( 'out.tgz', COMPRESS_GZIP );

# write a bzip compressed file
$tar->write( 'out.tbz', COMPRESS_BZIP );

# write a xz compressed file
$tar->write( 'out.txz', COMPRESS_XZ );

請注意,當您傳遞檔案處理常式時,會忽略壓縮引數,因為所有檔案都會逐字列印到您的檔案處理常式。如果您希望使用檔案處理常式啟用壓縮,請改用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 檔案處理常式。

第三個引數是一個可選的前置詞。所有檔案都將被放入您指定為前置詞的目錄中。因此,如果您在檔案中擁有檔案「a」和「b」,並且指定「foo」作為前置詞,它們將被寫入檔案為「foo/a」和「foo/b」。

如果沒有給定引數,write 會傳回整個格式化的檔案作為字串,如果您想將檔案塞進套接字或管道以進行 gzip 或其他操作,這會很有用。

$tar->add_files( @filenamelist )

取得一個檔名清單,並將它們新增到內存檔案中。

檔案路徑會自動轉換為類 Unix 格式,以便在壓縮檔中使用;如果是在 MacOS 上,檔案的修改時間會從 MacOS 紀元轉換為 Unix 紀元。因此,使用 Archive::Tar 在 MacOS 上建立的 tar 壓縮檔,可以用 Unix 上的 tar 和 MacOS 上的應用程式(例如 suntarStuffit Expander)來讀取。

請注意,檔案的類型/建立者和資源分支會遺失,這通常是跨平台壓縮檔所需要的。

除了檔名,您也可以傳遞現有的 Archive::Tar::File 物件,例如來自另一個壓縮檔。這個物件會被複製,實際上是原始物件的副本,而不是別名。

傳回剛才新增的 Archive::Tar::File 物件清單。

$tar->add_data ( $filename, $data, [$opthashref] )

接受一個檔名、一個包含完整資料的純量,以及一個指向特定選項雜湊的參考(選用)。

會將一個檔案新增到記憶體中的壓縮檔,檔名為 $filename,內容為 $data。可以使用 $opthashref 設定特定屬性。支援下列屬性清單:名稱、大小、mtime(上次修改日期)、模式、uid、gid、linkname、uname、gname、devmajor、devminor、prefix、type。(在 MacOS 上,檔案的路徑和修改時間會轉換為類 Unix 格式。)

檔案類型的有效值如下,這些常數由 Archive::Tar::Constant 定義:

FILE

一般檔案。

硬連結和符號(「軟」)連結;linkname 應指定目標。

CHARDEV
BLOCKDEV

字元和區塊裝置。devmajor 和 devminor 應指定主裝置和次裝置號碼。

目錄

目錄。

FIFO

FIFO(命名管線)。

SOCKET

Socket。

傳回剛剛新增的 Archive::Tar::File 物件,或在失敗時傳回 undef

$tar->error( [$BOOL] )

傳回目前的錯誤字串(通常是最後報告的錯誤)。如果指定了 true 值,它將提供錯誤的 Carp::longmess 等效值,實際上會提供堆疊追蹤。

為了向後相容,此錯誤也可用作 $Archive::Tar::error,儘管強烈建議您改用方法呼叫。

$tar->setcwd( $cwd );

Archive::Tar 需要知道目前的目錄,而且它會在每次從 tar 檔案中萃取相對項目並將其儲存在檔案系統中時執行 Cwd::cwd()。(不過,從版本 1.30 開始,Archive::Tar 會自動使用下面所述的速度最佳化,因此只有在您使用 extract_file() 時才相關。)

由於 Archive::Tar 在萃取 tarball 中的項目時不會在內部變更目前的目錄,因此只要我們可以保證目前的目錄不會在外部變更,就可以避免所有對 Cwd::cwd() 的呼叫。

若要使用此效能提升,請透過以下方式設定目前的目錄

use Cwd;
$tar->setcwd( cwd() );

在呼叫類似 extract_file 的函式之前設定一次,Archive::Tar 之後將使用目前的目錄設定,而且不會在內部呼叫 Cwd::cwd()

若要切換回預設行為,請使用

$tar->setcwd( undef );

Archive::Tar 將再次在內部呼叫 Cwd::cwd()

如果您使用 Archive::Tarextract() 方法,將會為您呼叫 setcwd()

類別方法

Archive::Tar->create_archive($file, $compressed, @filelist)

從提供的檔案清單建立 tar 檔案。第一個引數可以是所要建立的 tar 檔案名稱,也可以是開啟的檔案處理常式的參考(例如 GLOB 參考)。

第二個引數用於指示壓縮。您可以使用 gzipbzip2xz 進行壓縮。如果您傳遞一個數字,則假設它是 gzip 壓縮等級 (介於 1 到 9 之間),但建議使用常數

# write a gzip compressed file
Archive::Tar->create_archive( 'out.tgz', COMPRESS_GZIP, @filelist );

# write a bzip compressed file
Archive::Tar->create_archive( 'out.tbz', COMPRESS_BZIP, @filelist );

# write a xz compressed file
Archive::Tar->create_archive( 'out.txz', COMPRESS_XZ, @filelist );

請注意,當您傳遞檔案處理常式時,會忽略壓縮引數,因為所有檔案都會逐字列印到您的檔案處理常式。如果您希望使用檔案處理常式啟用壓縮,請改用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 檔案處理常式。

其餘的參數列出要包含在 tar 檔案中的檔案。這些檔案都必須存在。任何不存在或無法讀取的檔案都會被靜默略過。

如果檔案建立因任何原因失敗,create_archive 會傳回 false。請使用 error 方法來找出失敗的原因。

請注意,此方法並非即時寫入;它仍然會先將所有檔案讀入記憶體,然後才寫出檔案。如果這是個問題,請參閱以下常見問題解答。

Archive::Tar->iter( $filename, [ $compressed, {opt => $val} ] )

傳回一個迭代器函式,它會讀取 tar 檔案,而不會將其全部載入記憶體。每次呼叫此函式時,它會傳回 tarball 中的下一份檔案。這些檔案會以 Archive::Tar::File 物件傳回。當迭代器函式用盡所包含的檔案後,它會傳回空清單。

第二個參數可以是包含選項的雜湊參照,這些選項與傳遞給 read() 的參數相同。

範例用法

my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} );

while( my $f = $next->() ) {
    print $f->name, "\n";

    $f->extract or warn "Extraction failed";

    # ....
}

Archive::Tar->list_archive($file, $compressed, [\@properties])

傳回檔案中所有檔案名稱的清單。第一個參數可以是清單的 tar 檔案名稱,也可以是開啟檔案處理程序的參照(例如 GLOB 參照)。

如果 list_archive() 傳遞一個陣列參照作為其第三個參數,它會傳回一個雜湊參照清單,其中包含每個檔案的請求屬性。支援下列屬性清單:full_path、name、size、mtime(上次修改日期)、mode、uid、gid、linkname、uname、gname、devmajor、devminor、prefix、type。

有關支援屬性的詳細資訊,請參閱 Archive::Tar::File

傳遞僅包含一個元素('name')的陣列參照,會特別處理為傳回名稱清單,而不是雜湊參照清單。

Archive::Tar->extract_archive($file, $compressed)

解壓 tar 檔案的內容。第一個參數可以是建立的 tar 檔案名稱,也可以是開啟檔案處理的參考(例如 GLOB 參考)。tar 檔案中的所有相對路徑會在目前的作業目錄下建立。

extract_archive 會傳回已解壓的檔案清單。如果檔案解壓出於任何原因失敗,extract_archive 會傳回 false。請使用 error 方法找出失敗原因。

$bool = Archive::Tar->has_io_string

如果目前已載入 IO::String 支援,則傳回 true。

需要 IO::Stringperlio 支援才能支援寫入字串化檔案。目前,如果可行,perlio 是首選方法。

請參閱 GLOBAL VARIABLES 區段,了解如何變更此偏好設定。

$bool = Archive::Tar->has_perlio

如果目前已載入 perlio 支援,則傳回 true。

這需要 perl-5.8 或更高版本,並使用 perlio 編譯

需要 IO::Stringperlio 支援才能支援寫入字串化檔案。目前,如果可行,perlio 是首選方法。

請參閱 GLOBAL VARIABLES 區段,了解如何變更此偏好設定。

$bool = Archive::Tar->has_zlib_support

如果 Archive::Tar 可以解壓 zlib 壓縮的檔案,則傳回 true

$bool = Archive::Tar->has_bzip2_support

如果 Archive::Tar 可以解壓 bzip2 壓縮的檔案,則傳回 true

$bool = Archive::Tar->has_xz_support

如果 Archive::Tar 可以解壓 xz 壓縮的檔案,則傳回 true

Archive::Tar->can_handle_compressed_files

一個簡單的檢查常式,如果 Archive::Tar 可以使用 IO::ZlibIO::Compress::Bzip2IO::Compress::Xz 即時解壓縮壓縮的檔案,則傳回 true;如果兩者都未安裝,則傳回 false。

您可以使用這項捷徑來判斷在傳遞壓縮的檔案給 Archive::Tarread 方法之前,Archive::Tar 是否會執行您預期的動作。

全域變數

將此變數設定為 1,讓 Archive::Tar 在解壓縮時有效地複製檔案。預設值為 0,表示符號連結保持不變。當然,您也必須打包連結的檔案。

當您使用 writecreate_archive 寫入 tar 檔案時,會檢查此選項。

這項功能就像 /bin/tar-h 選項。

$Archive::Tar::CHOWN

預設情況下,Archive::Tar 會嘗試在有能力的情況下對您的檔案執行 chown。在某些情況下,這可能並非您所希望的。如果是這樣,請將此變數設定為 0 以停用 chown,即使有能力執行也是如此。

預設值為 1

$Archive::Tar::CHMOD

預設情況下,Archive::Tar 會嘗試對您的檔案執行 chmod,將其變更為檔案在檔案庫中指定的模式。在某些情況下,這可能並非您所希望的。如果是這樣,請將此變數設定為 0 以停用 chmod

預設值為 1

$Archive::Tar::SAME_PERMISSIONS

當啟用 $Archive::Tar::CHMOD 時,此設定會控制檔案庫中檔案的權限是否不加修改地使用,或者是否經過篩選,移除任何 setid 位元,並套用目前的 umask。

對於 root 使用者,預設值為 1;對於一般使用者,預設值為 0

$Archive::Tar::DO_NOT_USE_PREFIX

預設情況下,Archive::Tar 會嘗試將超過 100 個字元的路徑放入 tar 標頭的 prefix 欄位中,如 POSIX 標準所定義。然而,某些(較舊的)tar 程式並未實作此規範。若要與這些較舊版本或非 POSIX 相容版本保持相容性,你可以將 $DO_NOT_USE_PREFIX 變數設定為 true 值,而 Archive::Tar 將使用替代方式來處理超過 100 個字元的路徑,方法是使用 GNU Extended Header 功能。

請注意,不支援 GNU Extended Header 功能的用戶端將無法讀取這些檔案。此類用戶端包括 SolarisIrixAIX 上的 tar。

預設值為 0

$Archive::Tar::DEBUG

將此變數設定為 1 以隨時取得警告的 Carp::longmess 輸出,而不是一般的 carp。這是你可以透過執行下列動作取得的相同訊息

$tar->error(1);

預設值為 0

$Archive::Tar::WARN

如果你不想要列印任何警告,請將此變數設定為 0。我個人建議不要這麼做,但有人要求提供此選項。此外,請注意這當然不是執行緒安全的。

預設值為 1

$Archive::Tar::error

保留最後報告的錯誤。保留此變數是基於歷史原因,但強烈不建議使用。請改用 error() 方法

warn $tar->error unless $tar->extract;

請注意,在此模組的較舊版本中,error() 方法會傳回一個有效的全域值,即使如上所述以實例方法呼叫也是如此。此問題已獲得修正,而 Archive::Tar 的多個實例現在有各自的錯誤字串。

$Archive::Tar::INSECURE_EXTRACT_MODE

此變數表示 Archive::Tar 是否應允許將檔案解壓縮到目前的作業目錄之外。

允許此操作可能會產生安全性問題,因為惡意的 tar 檔案可能會變更或取代解壓縮使用者有權限存取的任何檔案。因此,預設值是不允許不安全的解壓縮。

如果您信任該檔案,或有其他理由允許檔案寫入目前工作目錄以外的檔案,請將此變數設定為 true

請注意,這是一個與 1.36 及之前版本不相容的變更。

$Archive::Tar::HAS_PERLIO

此變數包含一個布林值,表示我們目前是否載入 perlio 支援。這會在使用 perlio 編譯的任何大於 5.8 的 perl 中啟用。

如果您強烈建議停用它,請將此變數設定為 false。請注意,您需要安裝 IO::String 來支援寫入字串化的檔案。

除非您真的知道自己在做什麼,否則請勿變更此變數。

$Archive::Tar::HAS_IO_STRING

此變數包含一個布林值,表示我們目前是否載入 IO::String 支援。這會在任何具有可載入 IO::String 模組的 perl 中啟用。

如果您強烈建議停用它,請將此變數設定為 false。請注意,您需要從 perl 中取得 perlio 支援才能寫入字串化的檔案。

除非您真的知道自己在做什麼,否則請勿變更此變數。

$Archive::Tar::ZERO_PAD_NUMBERS

此變數包含一個布林值,表示我們是否會為 sizemtimechecksum 建立零填充數字。預設值為 0,表示我們會建立空白填充數字。新增此功能以與 busybox 實作相容。

	You can tune the behaviour by setting the $Archive::Tar::RESOLVE_SYMLINK variable,
	or $ENV{PERL5_AT_RESOLVE_SYMLINK} before loading the module Archive::Tar.

  Values can be one of the following:

		none
           Disable this mechanism and failed as it was in previous version (<1.88)

		speed (default)
           If you prefer speed
           this will read again the whole archive using read() so all entries
           will be available

    memory
           If you prefer memory

	Limitation

		It won't work for terminal, pipe or sockets or every non seekable source.

常見問題

執行 Archive::Tar 所需的 perl 最低版本為何?

您需要 perl 版本 5.005_03 或更新版本。

Archive::Tar 的速度是否很慢?

是的。它是純 perl,所以比你的 /bin/tar 慢很多。不過,它非常便於攜帶。如果速度是一個問題,請考慮改用 /bin/tar

Archive::Tar 在記憶體上比 /bin/tar 更重嗎?

是的,請參閱前一個答案。由於 Compress::Zlib 以及 IO::Zlib 不支援對其檔案句柄進行 seek,因此除了將檔案讀取到記憶體中之外別無選擇。如果你想對檔案進行記憶體內操作,這就可以了。

如果你只想提取,請改用 extract_archive 類別方法。它將立即最佳化並寫入磁碟。

另一個選項是使用 iter 類別方法來反覆處理 tarball 中的檔案,而不用一次性將它們全部讀取到記憶體中。

你可以改用延遲載入資料嗎?

在某些情況下可以。你可以使用 iter 類別方法來反覆處理 tarball 中的檔案,而不用一次性將它們全部讀取到記憶體中。

X kb tar 檔案需要多少記憶體?

可能超過 X kb,因為它將全部讀取到記憶體中。如果這是一個問題,而且你不需要對檔案進行記憶體內操作,請考慮改用 iter 類別方法或 /bin/tar

你如何處理檔案中不支援的檔案類型?

Unix 有幾種在其他平台上不支援的檔案類型,例如 Win32。如果我們遇到 hardlinksymlink,我們將嘗試複製原始檔案,而不是擲回錯誤。

這需要你首先將整個檔案讀入記憶體中,因為否則我們不知道要使用什麼資料來填入副本。(這表示你無法在檔案類型不相容的檔案中使用類別方法,包括 iter,並仍然期望一切正常運作)。

對於其他檔案類型,例如 chardevsblockdevs,我們會警告此特定項目無法正常解壓縮。

我使用 WinZip 或其他非 POSIX 軟體,而且檔案無法正確解壓縮!

預設情況下,Archive::Tar 處於完全相容於 POSIX 的模式,它使用 tar 的 POSIX 規格來儲存檔案。對於長度超過 100 個字元的路徑,這會使用 POSIX 標頭前綴 來完成。非 POSIX 相容的軟體可能不支援規格的這部分,而且可能只支援 GNU 延伸標頭 功能。為了讓這些軟體正常運作,你可以將 $Archive::Tar::DO_NOT_USE_PREFIX 變數設定為 true。有關此變數的詳細資訊,請參閱 全域變數 區段。

請注意,早於 1.14 版的 GNU tar 無法妥善處理 POSIX 標頭前綴。如果你使用此類版本,請考慮將 $Archive::Tar::DO_NOT_USE_PREFIX 變數設定為 true

如何從檔案中只解壓縮具有 X 屬性的檔案?

有時,你可能不想解壓縮整個檔案,只想要解壓縮與你相關的檔案,根據某些條件。

你可以透過根據條件篩選 Archive::Tar::File 物件清單來執行此操作。例如,若要只解壓縮標題中含有字串 foo 的檔案,你可以使用

$tar->extract(
    grep { $_->full_path =~ /foo/ } $tar->get_files
);

這樣一來,你可以根據檔案中的任何屬性進行篩選。請參閱 Archive::Tar::File 文件,了解如何使用這些物件。

如何存取 .tar.Z 檔案?

Archive::Tar 模組可以選擇使用 Compress::Zlib(透過 IO::Zlib 模組)來存取已使用 gzip 壓縮的 tar 檔案。不幸的是,使用 Unix compress 工具壓縮的 tar 檔案無法由 Compress::Zlib 讀取,因此 Archive::Tar 無法直接存取。

如果 uncompressgunzip 程式可用,您可以使用下列其中一種解決方法,從 Archive::Tar 讀取 .tar.Z 檔案

首先使用 uncompress

use Archive::Tar;

open F, "uncompress -c $filename |";
my $tar = Archive::Tar->new(*F);
...

接著使用 gunzip

use Archive::Tar;

open F, "gunzip -c $filename |";
my $tar = Archive::Tar->new(*F);
...

類似地,如果 compress 程式可用,您可以使用它來寫入 .tar.Z 檔案

use Archive::Tar;
use IO::File;

my $fh = IO::File->new( "| compress -c >$filename" );
my $tar = Archive::Tar->new();
...
$tar->write($fh);
$fh->close ;
如何處理 Unicode 字串?

Archive::Tar 使用位元組語意,針對從磁碟讀取或寫入的任何檔案。如果您只處理檔案,從不查看其內容,或僅使用位元組字串,這不會造成問題。但是,如果您使用具有字元語意的 Unicode 字串,則需要採取一些額外步驟。

例如,如果您新增一個 Unicode 字串,例如

# Problem
$tar->add_data('file.txt', "Euro: \x{20AC}");

稍後透過 $tar->write() 將 tar 檔案寫入磁碟時,就會發生問題

Wide character in print at .../Archive/Tar.pm line 1014.

資料已新增為 Unicode 字串,在寫入磁碟時,Archive::Tar 沒有設定 :utf8 列規範,因此 Perl 嘗試將字串轉換為 ISO-8859,但失敗了。寫入的檔案現在包含垃圾。

因此,在將 Unicode 字串傳遞給 add_data() 之前,需要將它們轉換為 UTF-8 編碼的位元組字串

use Encode;
my $data = "Accented character: \x{20AC}";
$data = encode('utf8', $data);

$tar->add_data('file.txt', $data);

如果你從 tarball 中抽取 UTF8 編碼檔案,會發生相反的問題。對 Archive::Tar::File 物件使用 get_content() 會將其內容傳回為位元組字串,而不是 Unicode 字串。

如果你想要它成為 Unicode 字串(因為你想要在正規表示式比對等操作中使用字元語意),你需要解碼 UTF8 編碼內容,並讓 Perl 將其轉換成 Unicode 字串。

use Encode;
my $data = $tar->get_content();

# Make it a Unicode string
$data = decode('utf8', $data);

Archive::Tar 中沒有辦法輕鬆提供此功能,因為 tarball 可能包含許多檔案,而且每個檔案都可能以不同的方式編碼。

注意事項

AIX tar 沒有用 0x00 填滿 tar 封存中的所有未使用空間。這有時會導致 Archive::Tar 顯示警告訊息。

Invalid header block at offset nnn

預計在以下 AIX 層級中發布此問題的修正程式,所有層級都應於 2009 年第 4 季推出

AIX 5.3 TL7 SP10
AIX 5.3 TL8 SP8
AIX 5.3 TL9 SP5
AIX 5.3 TL10 SP2

AIX 6.1 TL0 SP11
AIX 6.1 TL1 SP7
AIX 6.1 TL2 SP6
AIX 6.1 TL3 SP3

此問題的 IBM APAR 編號為 IZ50240(已報告的元件 ID:5765G0300 / AIX 5.3)。可以為此問題取得 ifix。如果你需要 ifix,請聯絡你當地的 IBM AIX 支援。

待辦事項

檢查傳入的控制代碼是否已開啟可讀寫

目前我不知道有任何可攜式的純 Perl 方式可以做到這一點。歡迎提出建議。

允許以字串形式傳入封存

目前,我們只允許開啟的檔案控制代碼或檔案名稱,而不允許字串。內部需要重新設計才能處理字串化的封存。

簡化處理已開啟的壓縮封存檔案控制代碼

目前,我們僅在 filehandle 為 IO::Zlib 物件時支援此功能。類似 apache 的環境會提供已開啟的 filehandle 至上傳的檔案,該檔案可能是壓縮的封存檔。

另請參閱

GNU tar 規範

https://gnu.dev.org.tw/software/tar/manual/tar.html

PAX 格式規範

tar 衍生的規範; http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html

GNU 與 POSIX tar 標準比較;http://www.delorie.com/gnu/docs/tar/tar_114.html
GNU tar 打算切換至 POSIX 相容性

GNU Tar 作者已表達他們打算完全相容 POSIX;https://gnu.dev.org.tw/software/tar/manual/html_node/Formats.html

各種 tar 實作比較

列出已知問題和不相容性;http://gd.tuwien.ac.at/utils/archivers/star/README.otherbugs

作者

此模組由 Jos Boumans <kane@cpan.org> 編寫。

請將錯誤報告至 <bug-archive-tar@rt.cpan.org>。

致謝

感謝 Sean Burke、Chris Nandor、Chip Salzenberg、Tim Heaney、Gisle Aas、Rainer Tammer,特別是 Andrew Savige 提供協助和建議。

版權

此模組的版權為 (c) 2002 - 2009 Jos Boumans <kane@cpan.org>。保留所有權利。

此函式庫為免費軟體;您可以在與 Perl 相同的條款下重新散布和/或修改它。