![从 tar 文件中查找提取的目录名称](https://linux22.com/image/72972/%E4%BB%8E%20tar%20%E6%96%87%E4%BB%B6%E4%B8%AD%E6%9F%A5%E6%89%BE%E6%8F%90%E5%8F%96%E7%9A%84%E7%9B%AE%E5%BD%95%E5%90%8D%E7%A7%B0.png)
我有一个项目,我正在下载并编译一堆文件。我可以对此文件做出的假设是:
- 只会有一个顶级目录
- 文件夹名称不一定与 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" ")
基本上,它的作用是捕获提取的输出,并获取第一行(这是顶级目录),然后 cd 进入其中。
所以,我的问题是,有没有更干净/更好的方法来做到这一点?
答案1
#!/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
在这里,我们获取 tar 中的文件列表,并使用head -1
cmd 获取第一行,使用 cut cmd 提取第一个字段。
答案2
如果您只有一个顶级目录,但什么也没有,您可以在运行 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]}"
这应该适用于所有具有算术for
、从零索引开始的数组以及用于${#arr[@]}
访问数组成员计数的 shell。
实际上存在一个问题,因为*/
可能会扩展到字面上*/
没有匹配的地方。在bash
(假设您因为标记而使用 bash)中,您可以进行设置shopt -s nullglob
。
使用*/
将通配项限制为目录,因此您不必担心文件 - 额外的文件仍然使其只有一个目录:)
答案3
使用 tar.bz2 文件,不要得到如下内容:
0 0 2019-04-02 17:20 folder name
我正在使用 -tf 选项:
tar -tf file_name.tar.bz2 | head -1 | cut -f1 -d"/"