Удалить несколько возможных суффиксов

Удалить несколько возможных суффиксов

Пример: Я хочу создать быструю команду для сжатия изображений (для моего файлового браузера).

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

Как указать, что следует удалить более одного суффикса?

решение1

basenameтребуется удалить только один суффикс и получить базовое имя (удалив компоненты каталога), которое вам в любом случае не нужно, поэтому basenameэто не совсем подходящий инструмент для ваших нужд.

Традиционный инструмент для извлечения данных из строки expr:

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

Но современные оболочки (такие как zsh, bash, ksh, ash, yash, все совместимые с POSIX sh...) имеют встроенные операторы для этого, так что в настоящее время они вам вряд ли понадобятся expr(и лучше этого избегать, поскольку с ними связано несколько проблем).

${var%pattern}

удаляет (наименьшую) часть, соответствующую шаблону из конца$var

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

Оболочки типа tcshили zshимеют операторы для удаления расширений. Zsh:

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

( rдляrootname).

Если вы хотите удалить только расширение 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

ГНУ 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

Связанный контент