Extrair nome de arquivo e extensão em Bash

Quero obter o nome do arquivo (sem extensão) e a extensão separadamente.

A melhor solução que encontrei até agora é:

NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`

Isto é errado porque não funciona't se o nome do arquivo contiver múltiplos . caracteres. Se, deixe's dizer, eu tenho a.b.js', ele irá considerara' e b.js', ao invés dea.b' e `js'.

Pode ser feito facilmente em Python com

file, ext = os.path.splitext(path)

mas I'preferiria não ligar um intérprete Python só por isto, se possível.

Alguma ideia melhor?

Solução

Primeiro, obtenha o nome do arquivo sem o caminho:

filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"

Alternativamente, você pode se concentrar no último '/' do caminho em vez do '.' que deve funcionar mesmo que você tenha extensões de arquivo imprevisíveis:

filename="${fullfile##*/}"

Você pode querer verificar a documentação :

Comentários (20)
~% FILE="example.tar.gz"
~% echo "${FILE%%.*}"
example
~% echo "${FILE%.*}"
example.tar
~% echo "${FILE#*.}"
tar.gz
~% echo "${FILE##*.}"
gz

Para mais detalhes, consulte expansão dos parâmetros da shell no manual do Bash.

Comentários (16)
pax> echo a.b.js | sed 's/\.[^.]*$//'
a.b
pax> echo a.b.js | sed 's/^.*\.//'
js

funciona bem, então você pode simplesmente usar:

pax> FILE=a.b.js
pax> NAME=$(echo "$FILE" | sed 's/\.[^.]*$//')
pax> EXTENSION=$(echo "$FILE" | sed 's/^.*\.//')
pax> echo $NAME
a.b
pax> echo $EXTENSION
js

Os comandos, a propósito, funcionam da seguinte forma.

O comando para NAME substitui um "." caracter seguido de qualquer número de não"." caracteres até o final da linha, sem nada (ou seja, remove tudo desde o "." até o final da linha, inclusive). Esta é basicamente uma substituição não mesquinha utilizando truques de regex.

O comando para EXTENSION substitui um qualquer número de caracteres seguido de um `""caractere no início da linha, com nada (ou seja, remove tudo desde o início da linha até o ponto final, inclusive). Esta é uma substituição gananciosa que é a ação padrão.

Comentários (1)