关于gzip:如何在不包括目录本身的情况下对文件和文件夹的目录进行tar?

How do I tar a directory of files and folders without including the directory itself?

我通常这样做:

1
tar -czvf my_directory.tar.gz my_directory

如果我只想在我的目录中包含所有内容(包括任何隐藏的系统文件),而不包括目录本身,该怎么办?我不想:

1
2
3
4
my_directory
   --- my_file
   --- my_file
   --- my_file

我想要:

1
2
3
my_file
my_file
my_file


使用tar的-C开关:

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

-C my_directory通知tar将当前目录改为my_directory,然后.表示"添加整个当前目录"(包括隐藏文件和子目录)。

确保在执行.之前执行-C my_directory,否则将在当前目录中获取文件。


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

应该在一行中完成这项工作。它对隐藏的文件也很有效。"*"至少在bash中不按路径名展开隐藏文件。下面是我的实验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ 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


您还可以像往常一样创建存档并用以下方法提取:

1
tar --strip-components 1 -xvf my_directory.tar.gz


请看一下--transform/--xform,当文件添加到存档中时,它可以给您按摩文件名的机会:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz
file2
.hiddenfile1
.hiddenfile2
file1

转换表达式类似于sed的表达式,我们可以使用除/以外的分隔符(上面的示例中是,)。https://www.gnu.org/software/tar/manual/html_部分/tar_52.html


TL DR;

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

with some(档案馆的唯一条件,dirs和符号链接):P></

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

解释

不幸的是他/她在the below the parent ./包括档案目录中:P></

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

You can move out of that the files目录的模式--transformusing the configuration option,but that get rid of the不.目录本身。它becomes to the command increasingly难驯服。P></

你可以使用$(find ...)to add to the command(文件列表类是答案,但Magnus),在"文件列表potentially原因太长"误差。最好的方式是与tar' EN S -T期权组合,这样:P></

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

基本上什么在文件列表(-type fdoes is),链接(-type l)和子目录的目录下(-type d)让你的文件名,然后使用相关的-printf"%P
"
,通that to the tar命令(它需要从stdin文件名使用-T -)。-Coption the needed is where the tar文件与我知道的关于names are并置。我知道that is the --no-recursion旗焦油不递归into is to Archive(folders告诉恩致复制文件)。P></

如果你需要给你一些特别的文件名(与滤波后的符号链接,等),findis the command powerful和漂亮,你可以测试它只是tarpart of the above the除尘命令:P></

1
2
3
4
5
6
7
$ find /my/dir/ -printf"%P
" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

如果你想filter for example文件PDF文件,! -name '*.pdf'P></

1
2
3
4
5
6
$ find /my/dir/ -printf"%P
" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

非GNU find

printf(the GNU命令uses available to which tells findfind)打印结果与ITS有关的路径。不管一个人多,如果你不有一个findGNU工程,这让the paths(removes有关父母与sed):P></

1
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 -


这个答案在大多数情况下都有效。但是请注意文件名是如何存储在tar文件中的,例如,./file1而不仅仅是file1文件。我发现,当使用此方法操作buildRoot中用作包文件的tarballs时,这会导致问题。

一种解决方案是使用一些bash globs列出除..以外的所有文件,如下所示:

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

这是我从这个答案中学到的一个技巧。

现在,如果没有与..?*.[^.]*匹配的文件,tar将返回一个错误,但它仍然可以工作。如果错误是一个问题(您正在检查脚本中是否成功),则此操作有效:

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

虽然现在我们正在处理shell选项,但我们可能会决定让*匹配隐藏文件更为简洁:

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

如果您的shell在当前目录中为*添加了全局变量,则这可能不起作用,因此,也可以使用:

1
2
3
4
5
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob


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


如果它是一个UNIX/Linux系统,并且您关心隐藏的文件(被*忽略),那么您需要执行以下操作:

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

我不知道在Windows下隐藏的文件是什么样子的。


我建议使用以下bash函数(第一个参数是目录的路径,第二个参数是结果存档的基名称):

1
2
3
4
5
6
7
8
9
10
function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'
'
    tar -C"$DIRPATH" -czf"$TARARCH" $( ls -a"$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

您可以这样运行它:

1
$ tar_dir_contents /path/to/some/dir my_archive

它将在当前目录中生成归档文件my_archive.tar.gz。它与隐藏的(.%)元素以及文件名中包含空格的元素一起使用。


1
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

这一个为我的工作都和它包含的文件在文件中没有隐放在根目录中的一个叫"类。"tomoe'答案:SP></


结果发现:扩路P></

我_ CD目录&;&;焦油czvf /我_ dir.tar.gz *。P></


1
2
3
4
5
6
7
8
# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
    { cd"$1" && find -type f -print0; } \
    | cut --zero-terminated --characters=3- \
    | tar --create --file="$2" --directory="$1" --null --files-from=-
}

使用空格或其他异常字符安全地处理文件名。您可以选择在find命令中添加-name '*.sql'或类似的过滤器,以限制包含的文件。


使用PAX。

pax是一个不受欢迎的包,但它以一种简单的方式完美地完成了工作。

1
pax -w > mydir.tar mydir


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

如果文件夹是mytemp,那么如果应用上面的文件,它将压缩并删除文件夹中的所有文件,但不单独保存。

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

您可以提供排除模式,也可以指定不查找子文件夹


1
tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`