複数の可能性のある接尾辞を削除する

複数の可能性のある接尾辞を削除する

例: 画像を縮小する簡単なコマンドを作成したい (ファイルブラウザ用)。

...
FN="/tmp/some-image.jpg"
gm convert "$FN" -resize 50% "$(dirname $FN)/$(basename $FN .jpg/png/gif).jpg"
...

複数のサフィックスを削除するように指定するにはどうすればよいでしょうか?

答え1

basename削除するには 1 つのサフィックスのみが必要で、ベース名 (ディレクトリ コンポーネントを削除) が提供されますが、これはいずれにしても必要ありません。そのため、basename実際にはニーズに適したツールではありません。

文字列からデータを抽出するための従来のツールは次のとおりですexpr

FN_without_extension=$(expr "x$FN" : 'x\(.*\)\.')

しかし、最近のシェル ( zsh、、、、、など、すべて POSIX 準拠) にはそのための組み込み演算子があるため、現在ではほとんど必要ありません(いくつかの問題があるためbash、使用を避けるのが最善です)。kshashyashshexpr

${var%pattern}

末尾からパターンに一致する(最小の)部分を削除します$var

gm convert "$FN" -resize 50% "${FN%.*}.jpg"

tcshまたはのようなシェルには、zsh拡張子を削除する演算子があります。 Zsh:

gm convert $FN -resize 50% $FN:r.jpg

rのためにルート名)。

拡張子を削除する場合、それが jpg/png/gif のいずれかである場合にのみ、手順はより複雑になり、シェルに依存します。

zsh

gm convert $FN -resize 50% ${FN%.(jpg|png|gif)}.jpg

ksh

gm convert "$FN" -resize 50% "${FN%.@(jpg|png|gif)}.jpg"

bash

shopt -s extglob
gm convert "$FN" -resize 50% "${FN%.@(jpg|png|gif)}.jpg"

expr

gm convert "$FN" -resize 50% "$(
  expr \( "x$FN" : '\(.*\)\.png$' \| \
          "x$FN" : '\(.*\)\.jpg$' \| \
          "x$FN" : '\(.*\)\.gif$' \| "x$FN" \) : 'x\(.*\)')".jpg

(はい、それは複雑です。そして、それは のいくつかの問題を回避するためですexpr)。

いくつかの実装ではexpr、次のように簡略化できます。

expr \( "x$FN" : '\(.*\)\.\(png\|jpg\|gif\)$' \| "x$FN" \) : 'x\(.*\)'

以下も使用できますsed:

FN_without_ext=$(printf '%s\n' "$FN" |
  sed -e '$!b' -e 's/\.png$//;t' -e 's/\.gif$//;t' -e 's/\.jpg$//')

大文字と小文字を区別しない場合は、png/gif/jpg上記のすべてのソリューションの を に置き換えることができます[pP][nN][gG]...。一部のシェル/ツールでは、大文字と小文字を区別しないマッチングも実行できます。

zsh:

 setopt extendedglob
 FN_without_ext=${FN%.(#i)(gif|png|jpg)}

ksh93:

 FN_without_ext=${FN%.~(i:gif|png|jpg)}

bash:

 shopt -s nocasematch
 LC_ALL=C
 if [[ $FN =~ (.*)\.(gif|png|jpg)$ ]]; then
   FN_without_ext=${BASH_REMATCH[1]}
 else
   FN_without_ext=$FN
 fi

GNU sed:

 FN_without_ext=$(printf '%s\n' "$FN" | sed -r '$s/\.(png|gif|jpg)$//I')

答え2

これでうまくいくでしょうか? 基本的には拡張機能を削除し.mp3ます.wav:

$ basename -s .wav $(basename -s .mp3 'some_file.mp3')
some_file
$ basename -s .wav $(basename -s .mp3 'some_file.wav')
some_file
$ basename -s .wav $(basename -s .mp3 'some_file.rs') 
some_file.rs

関連情報