我通常这样做:
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 -czvf my_directory.tar.gz my_directory
如果我只想在my_directory中包含所有内容(包括任何隐藏的系统文件),而不包括目录本身,该怎么办?我不想:
my_directory
--- my_file
--- my_file
--- my_file
我想要:
my_file
my_file
my_file
当前回答
命令
创建标准归档文件。
find my_directory/ -maxdepth 1 -printf "%P\n" | tar -cvf my_archive.tar -c my_directory/ - t -
打包文件和dirs文件在存档的根目录下,没有路径信息,较深的文件有相对路径。 没有奇怪的样子。”/'放在文件和dirs前面。(“。/文件”) 没有特殊文件。’。
似乎需要另一个工具,如find或ls (ls -A -1)来实现这些目标,而tar仅使用其参数无法根据这样的要求选择文件并创建存档。
使用上述命令创建一个tar归档文件,可以进一步处理或交付给某人,而不需要看起来奇怪或需要解释或工具来解压缩。
参数描述
maxdepth 1 最多下降1级-无递归。 printf 在标准输出上打印格式 %P文件的名称,删除它所在的起始点的名称。 \ n换行符 Printf不会在字符串的末尾添加换行符。必须加在这里
沥青: -C DIR,——directory=DIR 更改目录
-T FILE,——files-from=FILE 获取要从FILE中提取或创建的名称 - 上面的FILE是来自管道的标准输入
对其他解决方案的评论。
The same result might be achieved using solution described by @aross. The difference with the solution here is in that which tool is doing the recursing. If you leave the job to find, every filepath name, goes through the pipe. It also sends all directory names, which tar with --no-recursion ignores or adds as empty ones followed by all files in each directory. If there was unexpected output as errors in file read from find, tar would not know or care what's going on. But with further checks, like processing error stream from find, it might be a good solution where many options and filters on files are required. I prefer to leave the recursing on tar, it does seem simpler and as such more stable solution. With my complicated directory structure, I feel more confident the archive is complete when tar will not report an error.
@serendrewpity提出的另一个使用find的解决方案似乎很好,但它在带有空格的文件名上失败了。不同之处在于$()子shell提供的find输出是空格分隔的。可以使用printf添加引号,但这会使语句更加复杂。
当使用../my_archive.tar作为tar路径时,没有理由先cd到my_directory,然后再返回,因为tar有-C DIR,——directory=DIR命令,这就是为了这个目的。
使用。(dot)将包含圆点
使用*将让shell提供输入文件列表。可以使用shell选项来包含点文件。但这很复杂。该命令必须在允许的shell中执行。启用和禁用必须在tar命令之前和之后执行。如果根目录的未来存档包含太多的文件,它将失败。
最后一点也适用于所有不使用管道的解决方案。
大多数解决方案是创建一个目录,里面是文件和dirs。这几乎是人们所不希望看到的。
其他回答
这个答案在大多数情况下都适用。但是请注意tar文件中的文件名是如何存储的,例如,./file1而不仅仅是file1。我发现,在使用此方法操作作为BuildRoot包文件的tarball时,这会导致问题。
一种解决方案是使用一些Bash glob列出除..之外的所有文件。是这样的:
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选项,但我们可能会决定使用* match隐藏文件会更整洁:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
这可能不适用于当前目录下的shell glos *,所以,或者,使用:
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
这个方法对我很有用,它包含了所有隐藏文件,而不用把所有文件放在一个名为“。”的根目录中,就像tomoe的回答:
如果使用bash,这可能是最简单的答案。 使用shopt -s dotglob, bash命令将:
不包括根目录。 将包含根目录中的隐藏文件。
cd my_directory
shopt -s dotglob
tar -czvf ../my_directory.tar.gz *
shopt -u dotglob
(来自https://stackoverflow.com/a/9776491/7726468)
测试这个解决方案:
function tar.create() {
local folder="${1}"
local tar="$(basename "${folder}")".tar.gz
cd "${folder}" && tar -zcvf "../${tar}" .; cd - &> /dev/null
}
例子:
tar.create /path/to/folder
不客气
TL;DR (no ./和no ./file1!)
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
在某些条件下(只归档文件,dirs和符号链接):
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
例如,如果你想过滤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
Non-GNU找到
该命令使用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 -