获取文件名中的扩展名

获取文件名中的扩展名

如何从 bash 获取文件扩展名?这是我尝试过的:

filename=`basename $filepath`
fileext=${filename##*.}

通过这样做,我可以bz2从路径中获得扩展/dir/subdir/file.bz2,但我的路径有问题/dir/subdir/file-1.0.tar.bz2

如果可能的话,我更喜欢仅使用 bash 而不使用外部程序的解决方案。

为了清楚地说明我的问题,我正在创建一个 bash 脚本,只需通过单个命令即可提取任何给定的存档extract path_to_file。如何提取文件由脚本通过查看其压缩或归档类型来确定,可能是 .tar.gz、.gz、.bz2 等。我认为这应该涉及字符串操作,例如,如果我获得扩展名,.gz那么我应该检查它.tar之前是否有该字符串.gz- 如果有,则扩展名应该是.tar.gz.

答案1

您可以通过仅对文件名进行模式匹配而不是提取扩展名两次来简化问题:

case "$filename" in
    *.tar.bz2) bunzip_then_untar ;;
    *.bz2)     bunzip_only ;;
    *.tar.gz)  untar_with -z ;;
    *.tgz)     untar_with -z ;;
    *.gz)      gunzip_only ;;
    *.zip)     unzip ;;
    *.7z)      do something ;;
    *)         do nothing ;;
esac

答案2

如果文件名为file-1.0.tar.bz2,则扩展名为bz2.您用来提取扩展名 ( fileext=${filename##*.}) 的方法完全有效。

您如何决定扩展名是 or tar.bz2,而不是bz2or 0.tar.bz2?你需要先回答这个问题。然后您就可以找出哪些 shell 命令符合您的规范。

  • 一种可能的规范是扩展名必须以字母开头。这种启发式方法对于一些常见的扩展(例如 )会失败7z,最好将其视为特殊情况。这是 bash/ksh/zsh 的实现:

    basename=$filename; fileext=
    while [[ $basename = ?*.* &&
             ( ${basename##*.} = [A-Za-z]* || ${basename##*.} = 7z ) ]]
    do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    fileext=${fileext%.}
    

    为了 POSIX 可移植性,您需要使用case语句进行模式匹配。

    while case $basename in
            ?*.*) case ${basename##*.} in [A-Za-z]*|7z) true;; *) false;; esac;;
            *) false;;
          esac
    do …
    
  • 另一种可能的规范是某些扩展名表示编码并指示需要进一步剥离。这是 bash/ksh/zsh 实现(需要shopt -s extglob在 bash 和setopt ksh_globzsh 下):

    basename=$filename
    fileext=
    while [[ $basename = ?*.@(bz2|gz|lzma) ]]; do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    if [[ $basename = ?*.* ]]; then
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    fi
    fileext=${fileext%.}
    

    请注意,这被认为0file-1.0.gz.

相关结构位于 ${VARIABLE##SUFFIX}POSIX,因此它们可以在任何非古董 Bourne 风格的 shell 中工作,例如 ash、bash、ksh 或 zsh。

答案3

$ echo "thisfile.txt"|awk -F . '{print $NF}'

对此的评论在这里:http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/

答案4

有一天我创建了那些棘手的函数:

# args: string how_many
function get_last_letters(){ echo ${1:${#1}-$2:$2}; }
function cut_last_letters(){ echo ${1:0:${#1}-$2}; }

我发现这种简单的方法在很多情况下都非常有用,而不仅仅是在涉及扩展时。

用于检查扩展 -简单可靠

~$ get_last_letters file.bz2 4
.bz2
~$ get_last_letters file.0.tar.bz2 4
.bz2

对于切断延伸:

~$ cut_last_letters file.0.tar.bz2 4
file.0.tar

对于更改扩展名:

~$ echo $(cut_last_letters file.0.tar.bz2 4).gz
file.0.tar.gz

或者,如果您喜欢“方便的功能:

~$ function cut_last_letters_and_add(){ echo ${1:0:${#1}-$2}"$3"; }
~$ cut_last_letters_and_add file.0.tar.bz2 4 .gz
file.0.tar.gz

PS 如果您喜欢这些功能或发现它们有用,请参阅这篇文章:)(并希望发表评论)。

相关内容