Tar:仅提取文件(不提取子目录)

Tar:仅提取文件(不提取子目录)

我如何提取仅有的tar 存档中目录中的文件?我需要提取目录中的所有文件,而不是特定文件。例如,具有以下结构的 tar 存档:

wordpress
 --wp-admin
 --wp-content
 --wp-includes
 --index.php
 --license.txt
 --readme.html

我只想提取 WordPress 目录中的 3 个(或更多)文件,而不是子目录。

请注意,我可以在此站点上找到的其他解决方案是关于提取特定文件的。我的问题是关于提取全部文件。

答案1

除非我可以对目录名和文件名的格式做出假设,否则我无法找到任何在特定级别提取文件的方法,而不在同一级别提取(空)目录。 (如果文件名包含点但目录不包含点,则另一个答案就足够了。)

考虑370358.tar这个内容

wordpress/
wordpress/index.php
wordpress/license.txt
wordpress/readme.html
wordpress/wp-admin/
wordpress/wp-admin/admin.php
wordpress/wp-content/
wordpress/wp-content/2021/
wordpress/wp-content/2021/01/
wordpress/wp-content/2021/01/19/
wordpress/wp-content/2021/01/19/today.txt
wordpress/wp-content/content.txt
wordpress/wp-content/here.txt
wordpress/wp-content/some.txt
wordpress/wp-includes/

您可以wordpress/*像这样提取匹配的文件

tar xf /tmp/370358.tar --wildcards --exclude '*/*/*' && rmdir */* 2>/dev/null

ls -R wordpress
wordpress:
index.php  license.txt  readme.html

注意后面的rmdir.tar即使生成的目录为空,我们也无法告诉跳过目录创建,因此我们只需在之后删除它们即可。

如果您实际上并不希望该wordpress目录包含在提取中,

tar xf /tmp/370358.tar --strip-components 1 --wildcards --exclude '*/*/*' && rmdir * 2>/dev/null

ls -R
.:
index.php  license.txt  readme.html

答案2

假设使用 GNU tar,您可以通过一个简短的脚本提取存档bash

tar -x -f archive.tar --to-command=./script.sh

...script.sh可执行脚本在哪里

#!/bin/bash

if [ "$TAR_FILETYPE" = f ] &&
   [[ $TAR_FILENAME == wordpress/* ]] &&
   [[ $TAR_FILENAME != wordpress/*/* ]]
then
    mkdir -p "${TAR_FILENAME%/*}" &&
    cat >"$TAR_FILENAME" &&
    chmod "$TAR_MODE" "$TAR_FILENAME" &&
    chown "$TAR_UNAME:$TAR_GNAME" "$TAR_FILENAME" || true
else
    cat >/dev/null
fi

这里使用的变量TAR_*是由 GNU 在脚本环境中设置的tar,当前提取的文件的数据是通过标准输入到达的。

脚本中使用的测试是为了确保

  1. 我们正在提取的文件是一个常规文件,并且
  2. 该文件位于该wordpress目录中,而不是其他地方。

要提取文件,我们只需确保文件的目录存在,将标准输入重定向到正确的文件名,然后修改文件模式和所有权,以便权限和所有者正确。

显然,您也可以在命令行上内嵌脚本tar

tar -x -f archive.tar --to-command='bash -c "
    if [ \"\$TAR_FILETYPE\" = f ] &&
       [[ \$TAR_FILENAME == wordpress/* ]] &&
       [[ \$TAR_FILENAME != wordpress/*/* ]]
    then
        mkdir -p \"\${TAR_FILENAME%/*}\" &&
        cat >\"\$TAR_FILENAME\" &&
        chmod \"\$TAR_MODE\" \"\$TAR_FILENAME\" &&
        chown \"\$TAR_UNAME:\$TAR_GNAME\" \"\$TAR_FILENAME\" || true
    else
        cat >/dev/null
    fi"'

答案3

这会将目录中的所有文件提取到 tar 文件中,而无需进入子目录:

tar --wildcards --no-wildcards-match-slash -xvf file.tar.gz directory_in_tar/*.*

相关内容