Remova vários sufixos possíveis

Remova vários sufixos possíveis

Exemplo: quero criar um comando rápido para reduzir imagens (para meu navegador de arquivos).

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

Como posso especificar que mais de um sufixo deve ser removido?

Responder1

basenameleva apenas um sufixo para remover e fornece o nome base (remove os componentes do diretório) que você não deseja, portanto, basenamenão é realmente a ferramenta certa para sua necessidade.

A ferramenta tradicional para extrair dados de uma string é expr:

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

Mas os shells modernos (como zsh, bash, ksh, ash, yash, todos compatíveis com POSIX sh...) possuem operadores integrados para isso, então você quase nunca precisa exprhoje em dia (e é melhor evitá-lo, pois tem alguns problemas).

${var%pattern}

remove o padrão de correspondência de peça (menor) do final de$var

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

Os shells gostam tcshou zshpossuem operadores para remover extensões. Zsh:

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

( rparanome raiz).

Se você deseja remover a extensão, apenas se for jpg/png/gif, isso se torna mais complicado e depende do shell.

Com zsh:

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

Com ksh:

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

Com bash:

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

Com expr:

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

(sim, isso é complicado e serve para solucionar alguns dos problemas de expr).

Com algumas exprimplementações, pode ser simplificado para:

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

Você também pode usar sed:

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

Se você quiser que não diferencie maiúsculas de minúsculas, você pode substituir png/gif/jpgem todas as soluções acima por [pP][nN][gG]..., alguns shells/ferramentas também podem fazer correspondência sem distinção entre maiúsculas e minúsculas:

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')

Responder2

Isso deve funcionar? É basicamente remover .mp3ou .wavextensões:

$ 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

informação relacionada