从 tar 文件中查找提取的目录名称

bas*_*.gz 10 bash shell-script

我有一个项目,我正在下载和编译一堆文件。我可以对这些文件做出的假设是:

  • 只有一个顶级目录
  • 文件夹名称不一定与 tar.xz/gz 文件名匹配(换句话说,something-1.3.5a.tar.gz 可能会提取到一个名为 something-1.3.5 的文件夹中)

为了减少我必须做的打字量,我写了一个小脚本,其中包括以下内容:

  • 提取 tar.xz/gz 文件
  • cd 进入目录

我目前的黑客是做这样的事情:

test1=$(tar -axvf something-1.3.5a.tar.gz)

cd $(echo $test1 | cut -f1 -d" ")

基本上它的作用是捕获提取的输出,并获取第一行(这是顶级目录),然后将 cds 放入其中。

所以,我的问题是,有没有更清洁/更好的方法来做到这一点?

小智 12

#!/bin/sh
Dir_name=`tar -tzf something-1.3.5a.tar.gz | head -1 | cut -f1 -d"/"`
echo $Dir_name

tar options details,
-t, --list 
-z, --gzip, --ungzip               filter the archive through gzip
-f, --force-local              archive file is local even if has a colon
Run Code Online (Sandbox Code Playgroud)

在这里,我们获取 tar 中的文件列表并使用head -1cmd获取第一行,使用 cut cmd 提取第一个字段。

  • 需要注意的一点是,如果您使用 `set pipefail` 执行此操作,则会出现错误,因为 `head` 在第一行之后已终止。 (2认同)

Min*_*ang 1

如果您只有一个顶级目录,但什么也没有,您可以在运行 tar 之前记住有哪些目录,并在运行 tar 后查看您拥有的内容(假设没有其他人更改过该目录)。

 # ksh terminology: set -A BEFORE .*/ */
 BEFORE=(.*/ */)
 tar -xf blah blah blah
 AFTER=(.*/ */)
 # We can make it O(n), since glob outputs can be assumed to be sorted.
 # Do it.
 for (( i = 0; i < "${#BEFORE[@]}"; i++ )); do
    [ "${BEFORE[i]}" == "${AFTER[i]}" ] || break
 done
 cd "${AFTER[i]}"
Run Code Online (Sandbox Code Playgroud)

这应该适用于所有具有算术for、从零索引开始的数组以及用于${#arr[@]}访问数组成员计数的 shell。

实际上存在一个问题,因为*/可能会扩展到字面上*/没有匹配的地方。在bash(假设由于标签而使用 bash)中,您可以进行设置shopt -s nullglob

使用将*/通配项限制为目录,因此您不必担心文件 - 额外的文件仍然使其只有一个目录:)