ファイル名の拡張子を取得する

bashからファイル拡張子を取得するにはどうすればよいですか?これが私が試したことです:

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

そうすることで、パスからbz2の拡張子を取得できます/dir/subdir/file.bz2ですが、パス/dir/subdir/file-1.0.tar.bz2に問題があります。

外部なしでbashのみを使用するソリューションを希望します可能であればプログラム。

質問を明確にするために、extract path_to_fileの1つのコマンドだけで特定のアーカイブを抽出するbashスクリプトを作成していました。方法ファイルを抽出するかどうかは、圧縮またはアーカイブの種類(.tar.gz、.gz、.bz2など)を確認することでスクリプトによって決定されます。たとえば、拡張子が

次に、.gzの前に文字列.tarがあるかどうかを確認する必要があります。ある場合、拡張子は.tar.gzになります。

コメント

  • file = " /dir/subdir/file-1.0.tar.bz2

; echo $ {file ## *。}は、ここに'。bz2'を出力します。 '期待する出力は何ですか?

  • 必要な.tar.bz2
  • 関連:ファイル名と拡張子をBashで抽出します。
  • 回答

    ファイル名がfile-1.0.tar.bz2の場合、拡張子はbz2です。拡張機能の抽出に使用している方法(fileext=${filename##*.})は完全に有効です¹。

    拡張機能をtar.bz2であり、bz2または0.tar.bz2ではありませんか?最初にこの質問に答える必要があります。次に、何を理解できますかshellコマンドが仕様に一致します。

    • 可能な仕様の1つは、拡張子を文字で始める必要があることです。このヒューリスティックは、7z、これは特殊なケースとして扱うのが最適です。ここでは「sa 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 … 
    • もう1つの可能な仕様は、拡張子はエンコーディングを示し、さらにストリッピングが必要であることを示します。ここで「sabash / ksh / zshの実装(bashではshopt -s extglob、zshではsetopt ksh_globが必要):

      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 にあるため、これらは、ash、bash、ksh、zshなどの非アンティークのBourneスタイルのシェルで機能します。

    コメント

    • 最後の.トークンの前の文字列がアーカイブタイプであるかどうかを確認することで解決します。たとえば、tarである場合は、

    反復は終了する必要があります。

  • @uray:これはこの特定のケースでは機能しますが、'は一般的な解決策ではありません。 Maciej 'の.patch.lzma の例を検討してください。 isticは、最後の.の文字列を検討することです。'圧縮サフィックス(.7z.bz2.gz、…)、ストリッピングを続行します。
  • @NoamMインデントの何が問題になっていますか? 'は、編集後に間違いなく壊れています。二重にネストされたコードは、単一にネストされたコードと同じようにインデントされます。
  • 回答

    拡張子を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 

    コメント

    • このソリューションは非常にシンプルです。

    回答

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

    ここでのコメント: http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/

    コメント

    • .tar.gz拡張子では機能しません
    • まあ.tar .gzは実際にはgzipファイル内のtarであるため、gzipファイルからgz拡張子を削除するという意味で機能します。

    回答

    これが私のショットです:ドットを改行に変換し、tail、最後の行を取得:

    $> TEXT=123.234.345.456.456.567.678 $> echo $TEXT | tr . \\n | tail -n1 678 

    回答

    ある日、私はこれらのトリッキーな関数を作成しました。

    # 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これらの関数が気に入った場合、または使い切った場合は、この投稿を参照してください:)(そしてできればコメントを入れてください)。

    回答

    echo ${filename#$(echo $filename | sed "s/\.[^[:digit:]].*$//g;")} 

    例:

    コメント

    • すべての場合に機能するとは限りません。 ' foo.7z '
    • 引用符が必要な場合は、ファイル名に円記号が含まれている場合または-で始まる場合:"${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
    • @axel_c :そうです。例として、'はMaciejと同じ仕様を実装しました。 'が「文字で始まる」よりも優れているとあなたはどのようなヒューリスティックを提案しますか?
    • @Gilles:私はただそこにいると思います'既知の拡張子の事前計算されたリストを使用しない限り、解決策にはなりません。拡張子は何でもかまいません。

    回答

    ジャックマンのケースベースの回答は非常に優れており、移植性がありますが、変数にファイル名と拡張子が必要な場合は、この解決策を見つけました:

    INPUTFILE="$1" INPUTFILEEXT=$( echo -n "$INPUTFILE" | rev | cut -d"." -f1 | rev ) INPUTFILEEXT=$( echo -n $INPUTFILEEXT | tr "[A-Z]" "[a-z]" ) # force lowercase extension INPUTFILENAME="`echo -n \"$INPUTFILE\" | rev | cut -d"." -f2- | rev`" # fix for files with multiple extensions like "gbamidi-v1.0.tar.gz" INPUTFILEEXT2=$( echo -n "$INPUTFILENAME" | rev | cut -d"." -f1 | rev ) if [ "$INPUTFILEEXT2" = "tar" ]; then # concatenate the extension INPUTFILEEXT="$INPUTFILEEXT2.$INPUTFILEEXT" # update the filename INPUTFILENAME="`echo -n \"$INPUTFILENAME\" | rev | cut -d"." -f2- | rev`" fi 

    これは二重拡張子でのみ機能し、最初の拡張子は「tar」である必要があります。

    ただし、文字列長テストで「tar」テスト行を変更し、修正を複数回繰り返すことができます。 。

    回答

    これを使用して解決しました:

    filename=`basename $filepath` fileext=${filename##*.} fileext2=${filename%.*} fileext3=${fileext2##*.} if [ "$fileext3" == "tar" ]; then fileext="tar."$fileext fi 

    ただし、これは既知のアーカイブタイプ、この場合はtar

    でのみ機能します。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です