ファイル名の拡張子を取得します。

ファイル名の拡張子を取得します。

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

拡張子を2回抽出する代わりに、ファイル名のみをパターンマッチングして問題を単純化できます。

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あるかどうかをどのように決定しますか?まず、この質問に答える必要があります。これにより、どのシェルコマンドがあなたの仕様と一致するかを確認できます。bz20.tar.bz2

  • 可能な仕様の1つは、拡張子が文字で始まる必要があることです。この経験的な方法は、次のようないくつかの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 extglobbashと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%.}
    

    0考慮されますので参考にしてくださいfile-1.0.gz

および関連構造に位置 ${VARIABLE##SUFFIX}POSIXしたがって、ash、bash、ksh、zshなどのアンティークではなく、Bourneスタイルのシェルで動作します。

答え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この機能が気に入ったり役に立つと思われる場合は、この記事を参照してください:)(そしてコメントを残したい)

関連情報