我通常会这样做:
tar -czvf my_directory.tar.gz my_directory
如果我只想包含my_directory中的所有内容(包括任何隐藏的系统文件),但不包括该目录本身怎么办?我不想要:
my_directory
--- my_file
--- my_file
--- my_file
我想要:
my_file
my_file
my_file
使用 tar 的 -C
开关:
tar -czvf my_directory.tar.gz -C my_directory .
-C my_directory
表示告诉 tar 把当前目录切换到 my_directory
,然后 .
意味着“添加整个当前目录”(包括隐藏文件和子目录)。
确保在执行 .
命令之前先使用 -C my_directory
,否则您将会得到当前目录中的文件。
警告:您将会得到形如 ./file-name.ext
的条目而非 file-name.ext
!
如果您需要以 file-name.ext
形式的条目,请参考其他答案。
tar --create --file=foo.tar -C /etc passwd hosts -C /lib libc.a
我总是尝试 tar -czvf my_directory.tar.gz * -C my_directory
,但它不起作用。 -C
的位置很重要!该死的 tar... - m-riccd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
以下一行代码可以完成任务。它同样适用于隐藏文件。在bash中,"*"至少在路径名扩展中不会展开隐藏文件。以下是我的实验:
command */.*
$ 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
.
替换为 *
,那么命令就变成了 cd my_directory/ && tar -zcvf ../my_dir.tgz * && cd ..
,这样它就能像你期望的那样工作了。 - Anonymous$ (cd my_directory/ && tar -zcvf ../my_dir.tgz .)
- alecbztar
创建者一个很大的疏忽... - information_interchange您也可以像平常一样创建存档文件,并使用以下命令进行提取:
tar --strip-components 1 -xvf my_directory.tar.gz
--strip-components
是 GNU 的扩展功能。 - zneak。
作为根目录,则这并不能解决问题。 - WesternGun./
和./file1
!)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' answer中所示),但这可能会导致"文件列表过长"错误。最好的方法是将其与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
! -name '*.pdf'
。$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore
该命令使用printf
(在GNU find
中可用)告诉find
以相对路径打印其结果。但是,如果您没有GNU find
,则可以使用以下命令将路径转换为相对路径(使用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 -
.bashrc
中定义一个名为tar_content
的函数来执行此操作。 - WesternGun-T -
对我很有帮助。 - matt--transform
/--xform
,它给了你在将文件添加到归档时对文件名进行修改的机会。% 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
Transform表达式与sed
相似,我们可以使用除/
以外的分隔符(如上例中的,
)。
https://www.gnu.org/software/tar/manual/html_section/tar_52.html
cd my_directory
tar zcvf ../my_directory.tar.gz *
这个答案在大多数情况下都可以使用。但请注意,文件名以如下方式存储在tar文件中:./file1
而不仅仅是file1
。我发现,当使用此方法操作用作BuildRoot包文件的tarballs时,这会导致问题。
一种解决方法是使用一些Bash通配符列出除..
之外的所有文件,例如:
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
*
匹配隐藏文件更加整洁:shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
这种方法可能无法在当前目录中使用shell通配符*
,因此可以选择使用以下方式:
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
*
通配符在 tar 接管并更改目录(-C my_dir
)之前由 shell 进行评估。因此,它尝试将文件归档到 tar 命令执行的当前目录中,而不是更改后的目录 my_dir
。如果当前目录中的文件名恰好与更改后的目录 my_dir
中的名称匹配,则可能会有所帮助,但这通常不可靠。 :) ... 最有可能的是,这就是上述错误的原因。 - Trevorcd DIRECTORY
tar -czf NAME.tar.gz *
创建一个标准的压缩文件。
find my_directory/ -maxdepth 1 -printf "%P\n" | tar -cvf my_archive.tar -C my_directory/ -T -
打包的文件和目录在归档文件的根目录中,没有路径信息,更深层次的文件有相对路径。
没有奇怪的 './' 前缀在文件和目录名前。 ('./file')
不包括特殊文件 '.'。
看起来需要另外一个工具,比如 find
或者 ls
(ls -A -1
),tar
仅使用其参数无法选择文件并创建满足这些要求的压缩文件。
使用上述命令可以创建一个归档 tar 文件,可以进一步处理或交付给他人而不会出现奇怪的问题或需要解释或工具来解包。
-maxdepth 1
最多向下遍历 1 级,不递归。
-printf
在标准输出上打印格式
%P
文件的名称,去除找到它的起始点的名称。
\n
换行符
printf 不会在字符串末尾添加换行符,这里必须添加。
tar:
-C DIR
, --directory=DIR
切换到目录 DIR
-T FILE
, --files-from=FILE
从 FILE 中获取要提取或创建的名称
-
上面的 FILE 是标准输入,来自管道
与 @aross 描述的解决方案相同可能会达到相同的结果。
这里和那个解决方案的区别在于哪个工具正在递归。如果你让 find
去做这个工作,每个文件路径名都需要经过管道。它还会发送所有的目录名,而 tar
会忽略或添加为空的目录,接着添加每个目录中的所有文件。如果从 find
读取的文件中有意外的输出,tar 将无法知道或关心发生了什么。
但是,通过进一步的检查,例如处理来自 find 的错误流,它可能是一个需要对文件进行许多选项和筛选的好解决方案。
我更喜欢将递归放在 tar 上,这似乎是更简单、更稳定的解决方案。
在我的复杂目录结构中,当 tar 不报告错误时,我感觉压缩文件是完整的。
另一种使用find
的解决方案,由@serendrewpity提出,看起来不错,但是在文件名中包含空格时会失败。区别在于由$()子shell提供的find
输出被空格分隔。可能可以使用printf添加引号,但它会进一步复杂化语句。
没有必要先进入my_directory然后返回,同时在tar路径中使用../my_archive.tar,因为TAR有-C DIR
,--directory=DIR
命令,专门用于此目的。
使用.
(点)将包括点
使用*将让shell提供输入文件列表。可能可以使用shell选项来包括点文件。但这很复杂。命令必须在允许的shell中执行。启用和禁用必须在tar命令之前和之后进行。如果未来归档的根目录包含太多文件,则将失败。
最后一点也适用于所有不使用管道的解决方案。
大多数解决方案都会创建一个目录,其中包含文件和目录。这几乎从来不是所期望的。
|
只对标准输出起作用。任何打印到标准错误输出的内容都将无法传递给管道符右侧的 tar
,但默认会被打印到控制台上。
tar -czf
的默认行为吗?在我的情况下,它只存储文件而不是目录。当我仅对目录进行tar
操作时,它会包含目录,但是使用tar -czf
时,它只添加文件。 - Durga Swaroop