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
回答
ファイル名が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%.}
これにより、
0
がfile-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
でのみ機能します。