如何使用tar命令提取没有文件夹结构的文件

102

我有一个tar.gz文件,其结构如下:

folder1/img.gif
folder2/img2.gif
folder3/img3.gif

我想提取图像文件,而不保留文件夹结构,因此提取的结果看起来像这样:

/img.gif
/img2.gif
/img3.gif

我需要结合Unix和PHP来完成这件事。目前为止,我已经有了以下代码,它可以将它们提取到指定的目录中,但保留文件夹层次结构:

exec('gtar --keep-newer-files -xzf images.tgz -C /home/user/public_html/images/',$ret);

我猜你想要的不是手动迭代每个目录,将文件移动到你的路径并删除空文件夹吧?我不知道是否有隐藏的 --flatten 选项,但我可能错了。 - Jared Farrish
5个回答

176
你可以使用tar命令的--strip-components选项。
 --strip-components count
         (x mode only) Remove the specified number of leading path ele-
         ments.  Pathnames with fewer elements will be silently skipped.
         Note that the pathname is edited after checking inclusion/exclu-
         sion patterns but before security checks.
我创建了一个与你的结构类似的tar文件:

$tar -tf tarfolder.tar
tarfolder/
tarfolder/file.a
tarfolder/file.b

$ls -la file.*
ls: file.*: No such file or directory

然后通过执行以下操作进行提取:

$tar -xf tarfolder.tar --strip-components 1
$ls -la file.*
-rw-r--r--  1 ericgorr  wheel  0 Jan 12 12:33 file.a
-rw-r--r--  1 ericgorr  wheel  0 Jan 12 12:33 file.b

4
strip-components有最大使用数量吗?如果.tar文件仅包含一个文件夹层次结构,但strip-components为2,会发生什么?此外,strip-components会更改这些图像文件的名称还是只删除文件夹? - Ben Jackson
3
我建议你试着使用它,并找出对于你的具体情况是否适用。 - ericg
5
我尝试使用比目录结构中包含的数字更大的数字,结果也删除了文件。所以你必须知道要剥离的目录数的确切数量。 - Weston Ganger
2
这太棒了!只有一个问题,如果我们不知道要剥离多少个组件呢?而且我们只想获取文件,不要任何文件夹怎么办? - Dhiraj
注意:如果有一个没有子文件夹的文件夹(已经是平面结构),这意味着不会提取任何内容-->因此在将其应用于具有和不具有结构的混合文件夹时要小心。 - user1725306

33

使用tar命令中的--transform标志几乎可以实现这一点,但我认为没有办法删除剩余的目录。

这将使整个档案变得扁平:

tar xzf images.tgz --transform='s/.*\///'

输出结果将会是:

folder1/
folder2/
folder3/
img.gif
img2.gif
img3.gif
您将需要使用另一条命令删除这些目录,不幸的是。

2
在RHEL 6.2上,被接受的答案不起作用,但是这个答案可以(即使在_创建_存档时)。 :) 好耶! - bitcycle
我已经寻找这个东西有一段时间了。干得好!如果我不想要任何文件夹,只想要文件被提取出来怎么办? - Dhiraj
1
这太好了。截至目前(版本1.29),它甚至在解压期间都不会创建目录。 - Gerald Schneider
tar 1.23也没有创建目录。 - beluchin

22

检查 tar 版本,例如:

$ tar --version

如果版本>= tar-1.14.90,则使用--strip-components

tar xvzf web.dirs.tar.gz -C /srv/www --strip-components 2

否则使用 --strip-path

tar xvzf web.dirs.tar.gz -C /srv/www --strip-path 2

3
在mytar.tar.gz的任何子文件夹中查找img*.gif并提取到./

tar -zxf mytar.tar.gz --absolute-names --no-anchored img*.gif --transform='s:.*/::'

在mytar.tar.gz中列出的3个特定文件夹中查找img*.gif并提取到./

tar -zxf mytar.tar.gz --absolute-names --no-anchored img*.gif --transform='s:^folder[1-3]/::'


谢谢!提醒一下,“--absolute-names”选项在提取时好像没有起作用。我选择使用“--wildcards '*/filename-pattern'”而不是“--no-anchored 'filename-pattern'”,以确保我没有匹配到深层次的文件夹名称。感谢你指引我朝这个方向! - Barumpus

2
基于@ford的答案,这个将提取到my_dirname文件夹中。这样我们就可以正确清除空文件夹而不影响当前存在的文件。
tar xzf images.tgz --transform='s/.*\///' -C my_dirname
find my_dirname -type d -empty -delete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接