bash: como você retorna extensões de arquivo?

Quero escrever um script para retornar apenas a extensão do nome do arquivo de entrada. Por exemplo, textfile.txt deve retornar txt.

Eu “sou novo no Linux e bash, e eu” sou tentando aprender como escrever scripts básicos. Obrigado!

Comentários

  • Veja também stackoverflow.com/questions/965053/…
  • Qual é a extensão do linux-4.2.3.tar.xz arquivo que você pode baixar em kernel.org ? Qual é a extensão do arquivo /bin/bash que certamente está disponível em seu sistema? Veja, o conceito de ” extensão de arquivo ” é bem estranho no Linux. A parte após o ponto tem muito pouco significado para o sistema – é antes uma dica para o usuário sobre o que ele pode esperar desse arquivo. E essa dica pode mentir ou estar errada.

Resposta

O shell, bash por exemplo, tem muitos recursos de manipulação de string . Um deles permite remover tudo até um determinado padrão:

${VAR##GLOB} 

A sintaxe acima remove tudo da variável $VAR até a primeira correspondência do glob GLOB. Portanto, para imprimir a extensão de um arquivo sem seu nome, você pode fazer:

$ file="file.txt" $ echo ${file##*.} txt 

Observe que isso também pode lidar com mais de uma “extensão”:

$ file="file.new.txt" $ echo ${file##*.} txt 

Se você não quiser isso, use um #, que removerá a correspondência mais curta dos mais longos:

$ echo ${file#*.} new.txt 

Agora, para executar isso em todos os arquivos em um diretório, você pode fazer:

$ ls file.avi file.pdf file.png file.txt $ for file in *; do echo "$file : ${file##*.}"; done file.avi : avi file.pdf : pdf file.png : png file.txt : txt 

E, para fins de integridade, você também pode obter o nome do arquivo sem sua extensão usando ${file%.*}:

$ for file in *; do echo "$file : ${file##*.} : ${file%.*}"; done file.avi : avi : file file.pdf : pdf : file file.png : png : file file.txt : txt : file 

Comentários

  • isso não ‘ não funciona para coisas como foo / .git / bar / baz Acho que você poderia fazer echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘
  • @PaulM o que você quer dizer? Esse ‘ arquivo sa sem extensão, o que você esperaria obter com isso?
  • echo ” / foo /var/.git/foo/bar.bz” | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘. ‘ ‘ {print $ NF} ‘ == > > bz
  • @PaulM file="/foo/var/.git/foo/bar.bz"; echo "${file##*.}": bz. Não ‘ não vejo um problema.

Resposta

Com expansão do parâmetro :

$ x="textfile.txt" $ echo ${x##*.} txt 

O ${parameter##word} pattern remove o maior prefixo que corresponde a word (tudo exceto o final do arquivo).

Resposta

Um script bash muito simples que poderia fazer o que você quiser seria o seguinte:

#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}" 

O script é chamado como script.sh test.txt, e o que ele faz é

  • ele imprime $1 no stdout. $1 é o primeiro parâmetro fornecido ao script, neste caso test.txt.

  • a saída stdout de echo é canalizada para stdin para awk que divide a string (test.txt) em . e, em seguida, imprime o último elemento da divisão (txt neste caso).

Apenas um pequeno comentário, isso pode ser feito com uma linha, porque é uma “tarefa bastante simples:

echo test.txt | awk -F "." "{print $NF}" 

Comentários

  • Você precisa adicionar aspas $1 ou corre o risco de quebrar nomes de arquivo que contenham espaços etc.
  • isso não ‘ não funciona para coisas como foo / .git / bar / baz, acho que você poderia fazer echo test.txt | awk -F ‘ / ‘ ‘ {print $ NF} ‘ | awk -F ‘.’ ‘ {print $ NF} ‘

Resposta

#!/bin/bash my_file=`basename "$1"` # get full file name as a script parameter and strip the path my_extension="${my_file##*.}" my_file="${my_file%.*}" # will return base file name before the extension echo "$my_file" echo "$my_extension" 

Executar:

./script.sh index.html 

Resultado:

index html 

Mais informações: Expansão dos parâmetros do shell | gnu.org

Resposta

Para fazer isso, há várias advertências a levar em consideração:

  • O arquivo foo.d/bar não tem extensão, “não é um foo arquivo com um .
  • você também pode querer considerar que .bashrc não tem extensão
  • O . e .. arquivos de diretórios especiais provavelmente devem ser tratados de maneira especial e considerados como não tendo qualquer extensão.
  • qual é a extensão para file.tar.gz? gz ou tar.gz? E quanto a holiday.picture.jpg ou bash-4.4?
  • O que você deve retornar por foo.d/? Vazio ou d?

Aqui, eu “faria:

#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done 

Comentários

  • Excelente tratamento de respostas, também as advertências usuais e código útil, especialmente como uma função.

Resposta

Vou lançar mais algumas opções caso você tenha sed ou Perl instalado:

 #!/bin/bash ext=$(<<<"$1" sed -n "s/^[^.]*\.//p") printf "Extension: $ext\n" ext=$(<<<"$1" perl -ne "s/^.*?\.//&&print") printf "Extension: $ext\n" exit 0  
  • s/^[^.]*\.//p em sed e s/^.*?\.//&&print em perl: tente substituir a sequência mais curta de caracteres não . seguido por um . caractere no início da string; se a substituição puder ser feita, imprima o resultado da substituição;
 % bash script.sh file.bin Extension: bin Extension: bin  

Resposta

Tenha cuidado. No Unix / Linux (e MacOS), a “extensão do nome do arquivo” é apenas informativa (se tanto). Você pode perfeitamente ter um script Perl chamado photo.gif ou um arquivo GIF chamado poem.txt. Ou até mesmo um arquivo chamado some.txt.png.

Comentários

  • It ‘ é igualmente informativo no MS Windows, ‘ é apenas que lá o programa shell padrão faz suposições mais fortes sobre o emparelhamento extensão – conteúdo, e deve haver um incompatibilidade entre nomenclatura e conteúdo, a coisa toda geralmente começa a gritar erros, coitadinho.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *