如何使用 bash 脚本取消 tar 目录中每种类型的 tar 文件?

How to untar every type of tar file in a directory with bash script?

我是为自动化任务编写 bash 脚本的初学者,我正在尝试取消 tar 一个目录中的所有 tar 文件(也有很多方法许多人手工完成)以获得一堆源代码文件。它们都是 *.tar.gz、*.tar.xz 或 *.tar.bz2.

类型

这是我正在执行的 Linux from Scratch LFS 安装(我是初学者),我不确定除了使用 bash 脚本。我的小脚本的代码在下面。

#!/bin/bash
for afile in 'ls -1'; do
    if [ 'afile | grep \"\.tar\.gz\"' ];
    then
        tar -xzf afile
    elif [ 'afile | grep \"\.tar\.xz\"' ]
    then
        tar -xJf afile
    elif [ 'afile | grep \"\.tar\.xz\"' ]
    then
        tar -xjf afile
    else
        echo "Something is wrong with the program"
    fi
done;

我原以为它会取消tar目录中的所有内容并创建单独的目录,但它却退出并出现此错误:

tar (child): afile: Cannot open: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

显然它认为 afile 是实际文件,但我不知道如何将 afile 更改为正在通过我的 for 构造的每个文件。我将如何为此编写脚本,尤其是因为有不同类型的文件?

要让您的脚本以最少的更改工作,请在需要变量值时使用 $afile。美元符号是一个变量引用;否则你只会得到文字字符串 'afile'。也去掉方括号,取而代之的是 echo 变量 grep.

for afile in `ls -1`; do
    if echo "$afile" | grep '\.tar\.gz'
    then
        tar -xzf "$afile"
    elif echo $afile | grep '\.tar\.xz'
    then
        tar -xJf "$afile"
    elif echo "$afile" | grep '\.tar\.bz2'
    then
        tar -xjf "$afile"
    else
        echo "Something is wrong with the program"
    fi
done

由于您是 bash 初学者,让我们看看您可以用其他各种方式编写脚本。我会做一些改进。其一,you shouldn't loop over ls。您可以通过遍历 * 得到同样的结果。其次,grep是一个重量级的工具。您可以使用 [[==.

等内置 shell 结构进行一些简单的字符串比较
for afile in *; do
    if [[ "$afile" == *.tar.gz ]]; then
        tar -xzf "$afile"
    elif [[ "$afile" == *.tar.xz ]]; then
        tar -xJf "$afile"
    elif [[ "$afile" == *.tar.bz2 ]]; then
        tar -xjf "$afile"
    else
        echo "Something is wrong with the program"
    fi
done

实际上,使用 case 语句会更好。让我们试试吧。另外让我们用 >&2 将错误消息回显到 stderr。这总是个好主意。

for afile in *; do
    case "$afile" in
        *.tar.gz)  tar -xzf "$afile";;
        *.tar.xz)  tar -xJf "$afile";;
        *.tar.bz2) tar -xjf "$afile";;
        *) echo "Something is wrong with the program" >&2
    esac
done

如果我们只列出我们想要循环的三种类型的文件,我们甚至可以摆脱错误消息。那就没办法打else了。

for afile in *.tar.{gz,xz,bz2}; do
    case "$afile" in
        *.tar.gz)  tar -xzf "$afile";;
        *.tar.xz)  tar -xJf "$afile";;
        *.tar.bz2) tar -xjf "$afile";;
    esac
done

或完全不同的方法:使用 find 查找所有文件及其 -exec 操作为找到的每个文件调用一个命令。这里 {} 是它找到的文件的占位符。

find . -name '*.tar.gz'  -exec tar -xzf {} \;
find . -name '*.tar.xz'  -exec tar -xJf {} \;
find . -name '*.tar.bz2' -exec tar -xjf {} \;