Como obtenho a extensão de arquivo do bash? Aqui está o que eu tentei:
filename=`basename $filepath`
fileext=${filename##*.}
Ao fazer isso, posso obter a extensão do bz2
caminho /dir/subdir/file.bz2
, mas tenho um problema com o caminho /dir/subdir/file-1.0.tar.bz2
.
Eu preferiria uma solução usando apenas o bash sem programas externos, se possível.
Para deixar minha pergunta clara, eu estava criando um script bash para extrair qualquer arquivo especificado apenas com um único comando de extract path_to_file
. Como extrair o arquivo é determinado pelo script vendo sua compressão ou arquivamento tipo, que poderia ser .tar.gz, .gz, .bz2 etc. Eu acho que isso deve envolver a manipulação de cadeia, por exemplo, se eu chegar a extensão .gz
então eu deve verificar se possui a string .tar
antes .gz
- se houver, a extensão deve estar .tar.gz
.
.tar.bz2
Respostas:
Se o nome do arquivo for
file-1.0.tar.bz2
, a extensão serábz2
. O método que você está usando para extrair a extensão (fileext=${filename##*.}
) é perfeitamente válido¹.Como você decide que deseja que a extensão seja ou
tar.bz2
nãobz2
ou0.tar.bz2
? Você precisa responder a essa pergunta primeiro. Então você pode descobrir qual comando shell corresponde à sua especificação.Uma especificação possível é que as extensões devem começar com uma letra. Essa heurística falha em algumas extensões comuns como
7z
, que podem ser melhor tratadas como um caso especial. Aqui está uma implementação bash / ksh / zsh:Para portabilidade POSIX, você precisa usar uma
case
instrução para correspondência de padrões.Outra especificação possível é que algumas extensões denotam codificações e indicam que é necessária mais remoção. Aqui está uma implementação do bash / ksh / zsh (exigindo
shopt -s extglob
no bash esetopt ksh_glob
no zsh):Observe que isso considera
0
uma extensão emfile-1.0.gz
.¹ e construções relacionadas estão no POSIX , portanto, eles funcionam em qualquer shell não-Bourne antigo, como ash, bash, ksh ou zsh.
${VARIABLE##SUFFIX}
fonte
.
token é do tipo archive, por exemplotar
, se não for do tipo archive, como a0
iteração, deve terminar..patch.lzma
. A melhor heurística seria considerar a corda após o último.
: se é um sufixo de compressão (.7z
,.bz2
,.gz
, ...), continuar a descascar.Você pode simplificar as coisas apenas fazendo a correspondência de padrões no nome do arquivo em vez de extrair a extensão duas vezes:
fonte
Comentários sobre isso aqui: http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/
fonte
.tar.gz
extensãoAqui está minha chance: traduza pontos para novas linhas, passe através
tail
, obtenha a última linha:fonte
Por exemplo:
fonte
printf
caso o nome do arquivo contenha uma barra invertida ou comece com-
:"${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
Um dia eu criei essas funções complicadas:
Eu achei essa abordagem direta, muito útil em muitos casos, não apenas quando se trata de extensões.
Para verificar extensões - É simples e confiável
Para extensão de corte:
Para alterar a extensão:
Ou, se você gosta de "funções úteis:
PS Se você gostou dessas funções ou as encontrou usadas por inteiro, consulte este post :) (e espero colocar um comentário).
fonte
a resposta baseada em casos de jackman é muito boa e portátil, mas se você quiser apenas o nome do arquivo e a extensão em uma variável, encontrei esta solução:
Funciona apenas com extensões duplas e a primeira deve ser "tar".
Mas você pode alterar a linha de teste "tar" com um teste de comprimento de sequência e repetir a correção várias vezes.
fonte
eu resolvi usando isso:
mas isso funciona apenas para o tipo de arquivamento conhecido, neste caso apenas
tar
fonte