gzip - tgz - unzip tar file command




如何在不包含目錄本身的情況下tar文件和文件夾的目錄? (10)

我通常會這樣做:

tar -czvf my_directory.tar.gz my_directory

如果我只想將所有內容(包括任何隱藏的系統文件)包含在my_directory中,而不是目錄本身? 我不想要:

my_directory
   --- my_file
   --- my_file
   --- my_file

我想要:

my_file
my_file
my_file

TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

有一些條件(僅存檔文件,目錄和符號鏈接):

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

說明

不幸的是,在存檔中包含父目錄./

tar -czf mydir.tgz -C /my/dir .

您可以使用--transform配置選項將所有文件移出該目錄,但這並不能解決問題. 目錄本身。 馴服命令變得越來越困難。

您可以使用$(find ...)為命令添加文件列表(如magnus的答案 ),但這可能會導致“文件列表太長”錯誤。 最好的方法是將它與tar的-T選項結合使用,如下所示:

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

基本上它是在你的目錄下列出所有文件( -type f ),鏈接( -type l )和子目錄( -type d ),使用-printf "%P\n"使所有文件名相對,然後將其傳遞給tar命令(它使用-T -從STDIN獲取文件名)。 需要-C選項,以便tar知道具有相對名稱的文件所在的位置。 --no-recursion標誌是這樣的,tar不會遞歸到它被告知要歸檔的文件夾中(導致重複的文件)。

如果你需要做一些特殊的文件名(過濾,符號鏈接等), find命令非常強大,你可以通過刪除上述命令的tar部分來測試它:

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

例如,如果您要過濾PDF文件,請添加! -name '*.pdf' ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

非GNU查找

該命令使用printf (在GNU find可用),它告訴find用相對路徑打印結果。 但是,如果你沒有find GNU,這可以使路徑相對(使用sed刪除父項):

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

share應該在大多數情況下工作。 然而,請注意文件名是如何存儲在tar文件中的,例如./file1而不僅僅是file1 。 我發現這在使用這種方法來操作用作BuildRoot包文件的tarball時造成了問題。

一個解決方案是使用一些Bash globs列出除..之外的所有文件,如下所示:

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

這是我從這個答案中學到的一個技巧。

現在tar會返回一個錯誤,如果沒有匹配..?*.[^.]* ,但它仍然可以工作。 如果錯誤是一個問題(您正在腳本中檢查是否成功),那麼這將起作用:

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

雖然現在我們正在搞亂shell選項,但我們可能會認為更匹配隱藏文件:

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

這可能不適用於當前目錄中的外殼* ,所以可以使用:

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob

使用tar的-C開關:

tar -czvf my_directory.tar.gz -C my_directory .

-C my_directory通知tar將當前目錄更改為my_directory ,然後. 意思是“添加整個當前目錄”(包括隱藏文件和子目錄)。

確保在執行之前先執行-C my_directory . 否則你會得到當前目錄中的文件。


如果它是一個Unix / Linux系統,並且你關心隱藏的文件(這些文件將被*忽略),你需要做的是:

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

我不知道Windows下隱藏的文件是什麼樣子。


我會提出以下Bash函數(第一個參數是dir的路徑,第二個參數是生成的歸檔的基本名稱):

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

你可以這樣運行它:

$ tar_dir_contents /path/to/some/dir my_archive

它會在當前目錄中生成存檔my_archive.tar.gz 。 它適用於隱藏的(。*)元素以及其文件名中帶有空格的元素。


我發現最簡單的方法:

cd my_dir && tar -czvf ../my_dir.tar.gz *


 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

如果該文件夾是mytemp,那麼如果您應用上述內容,它將壓縮並刪除該文件夾中的所有文件,但不保留它

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

您可以提供排除模式,也可以指定不要查看子文件夾


cd my_directory
tar zcvf ../my_directory.tar.gz *

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

應該在一行中完成這項工作。 它也適用於隱藏文件。 “*”不會通過路徑名擴展至少在bash中擴展隱藏文件。 以下是我的實驗:

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

find $TARGET_DIR -maxdepth 1 -type f -print0 \
| xargs --null --max-args 1 basename --zero \
| tar --create --file=result.tar --directory=$TARGET_DIR --null --files-from=-

假設您不想包含任何子目錄或任何子目錄中的任何文件。 使用空格或其他不尋常的字符安全處理文件名。 您可以選擇在find命令中添加一個-name '*.sql'或類似的過濾器來限制包含的文件。