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
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 casotest.txt
. -
a saída stdout de
echo
é canalizada para stdin paraawk
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 é umfoo
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
outar.gz
? E quanto aholiday.picture.jpg
oubash-4.4
? - O que você deve retornar por
foo.d/
? Vazio oud
?
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
emsed
es/^.*?\.//&&print
emperl
: 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.
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.