'ls -1': como listar nomes de arquivos sem extensão

17

ls -1 lista meus elementos da seguinte forma:

foo.png
bar.png
foobar.png
...

Eu quero que ele seja listado sem o .png , assim:

foo
bar
foobar
...

(o diretório contém apenas .png arquivos)

Alguém pode me dizer como usar grep neste caso?

Objetivo: Eu tenho um arquivo de texto onde todos os nomes são listados sem a extensão. Eu quero fazer um script que compara o arquivo de texto com a pasta para ver qual arquivo está faltando.

    
por Colin 18.05.2016 / 12:41

15 respostas

38

Você só precisa do shell para este trabalho.

POSIXly:

for f in *.png; do
    printf '%s\n' "${f%.png}"
done

com zsh :

print -rl -- *.png(:r)
    
por 18.05.2016 / 12:52
31
ls -1 | sed -e 's/\.png$//'

O comando sed remove (isto é, substitui pela string vazia) qualquer string .png encontrada no end de um nome de arquivo.

O . é salvo como \. , de modo que é interpretado por sed como um caractere literal . , em vez do coexe% regexp% (que corresponde a qualquer caractere). O . é a âncora de fim de linha, portanto, não corresponde a $ no meio de um nome de arquivo.

    
por 18.05.2016 / 12:56
15

Se você quiser apenas usar o bash:

for i in *; do echo "${i%.png}"; done

Você deve alcançar grep ao tentar encontrar correspondências, e não remover / substituir por sed mais apropriado:

find . -maxdepth 1 -name "*.png"  | sed 's/\.png$//'

Depois que você decidir criar alguns subdiretórios para organizar seus arquivos PNG, altere-os facilmente para:

find . -name "*.png"  | sed 's/\.png$//'
    
por 18.05.2016 / 12:46
12

Eu escolheria basename (assumindo a implementação do GNU):

basename --suffix=.png -- *
    
por 18.05.2016 / 17:18
9

Outra resposta muito semelhante (estou surpreso que essa variante ainda não tenha aparecido) é:

ls | sed -n 's/\.png$//p'
  • Você não precisa da opção -1 para ls , pois ls assume que, se a saída padrão não for um terminal (é um canal, nesse caso).
  • a opção -n para sed significa "não imprimir a linha por padrão"
  • a opção /p no final da substituição significa "... e imprima esta linha se uma substituição tiver sido feita".

O efeito líquido disso é imprimir apenas as linhas que terminam em .png , com o .png removido. Ou seja, isso também atende à pequena generalização da pergunta do OP, em que o diretório não contém apenas .png de arquivos.

A técnica sed -n costuma ser útil em casos em que você poderia usar o grep + sed.

    
por 18.05.2016 / 18:17
7

Você pode usar apenas comandos BASH para fazer isso (sem ferramentas externas).

for file in *; do echo "${file%.*}"; done 

Isso é útil quando você está sem / usr / bin e funciona bem para nomes de arquivos como this.is.image.png e para todas as extensões.

    
por 18.05.2016 / 18:24
5

Não é seguro analisar ls ou canalizar find [ 1 , 2 ]

Não é seguro analisar (e canalizar) a saída de ls ou find , principalmente porque é possível encontrar nos nomes de arquivo caracteres não usuais como newline , a aba ... Aqui um ciclo de shell puro funcionará [ cuonglm ]

Mesmo o comando find não canalizado com a opção -exec funcionará:

find ./*.png  -exec  basename {} .png  \;

Atualizações / Notas : você pode usar find . para pesquisar até mesmo pelos arquivos ocultos ou find ./*.png para obter apenas os não ocultos. Com find *.png -exec ... você pode ter problema no caso de estar presente um arquivo chamado .png porque o find irá obtê-lo como opção. Você pode adicionar -maxdepth 0 para evitar descer em diretórios nomeados como Dir_01.png , ou find ./*.png -prune -exec ... quando maxdepth não é permitido (obrigado Stéphane). Se você quiser evitar listar esses diretórios, deverá adicionar a opção -type f (que também excluiria outros tipos de arquivos não regulares). Dê uma olhada no man para um panorama mais completo sobre todas as opções disponíveis e lembre-se de verificar quando eles são compatíveis com POSIX, para uma melhor portabilidade.

Algumas palavras mais

Pode acontecer, por exemplo, copiar o título de um documento e colá-lo no nome do arquivo, uma ou mais novas linhas terminarão no próprio nome do arquivo. Podemos ser ainda mais infelizes que um título possa conter até mesmo a chave que temos de usar antes de uma nova linha:

The new art of working on .png
files and other formats.

Se você quiser testar, você pode criar nomes de arquivo como este com os comandos

touch "A file with two lines"$'\n'"and This is the second.png"
touch "The new art of working on .png"$'\n'"files and other formats.png"

O simples /bin/ls *png produzirá ? em vez dos caracteres não imprimíveis

A file with two lines?and This is the second.png
The new art of working on .png?files and other formats.png

Em todos os casos em que você enviará a saída de ls ou find , o seguinte comando não terá nenhuma dica para entender se a linha atual vem de um novo arquivo name ou se segue um caracter newline no precedente nome do arquivo . Um nome desagradável de fato, mas ainda legal.

Um ciclo de shell com um shell Expansão de Parâmetros, ${parameter%word} , na variante com printf ou echo funcionará [ cuonglm ], [ Anthon1 ] .

for f in *.png; do printf "%s\n" "${f%.png}" ; done

A partir da página man da Expansão do Parâmetro do Shell [ 3 ]

${parameter%word}
${parameter%%word}

... the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted.

    
por 19.05.2016 / 02:30
4

não foi o suficiente?

ls -1 | sed 's/\.png//g'

ou, em geral, isso

ls -1 | sed 's/\.[a-z]*//g'

removerá todas as extensões

    
por 18.05.2016 / 15:44
2

Use rev :

ls -1 | rev | cut -f 2- -d "." | rev

rev inverte todas as strings (linhas); você corta tudo depois do primeiro '. e reverte novamente o remanescente.

Se você quiser grep 'alma':

ls -1 | rev | cut -f 2- -d "." | rev | grep 'alma'
    
por 18.05.2016 / 13:56
2

de acordo com o seu comentário "Eu tenho um arquivo de texto onde todos os nomes são listados sem a extensão. Eu quero fazer um script PHP que compara o arquivo de texto com a pasta para ver qual arquivo está faltando":

for file in $(cat yourlist) ; do
  [ -f "${file}.png" ] || {
    echo "$file : listed in yourlist, but missing in the directory"
  }
done
#assumes that filenames have no space...
# otherwise use instead:
#  while IFS= read file ; do ...(same inner loop as above)... ; done < yourlist

e o inverso:

for file in *.png ; do
  grep "^${file%.png}$" yourlist >/dev/null || {
    echo "$file: present in the directory but not listed in yourlist"
  }
done
#I assume there are no spaces/tabs/? before/after names in 'yourlist'. Change the script accordingly if there are some (or sanitize the list)
    
por 20.05.2016 / 11:29
1

ls -l | sed 's/\.png$//'

É o método mais preciso, conforme destacado pelo @roaima. Sem os arquivos \.png com escape chamados a_png.png seriam listados como: a_ .

    
por 18.05.2016 / 12:56
1

Se eu soubesse que o diretório tinha apenas arquivos com extensão .png, eu teria acabado de executar: ls | awk -F. '{print $1}'

Isso retornará o primeiro "campo" para qualquer coisa onde houver um nome de arquivo.extensão.

Exemplo:

[rsingh@rule51 TESTDIR]$ ls
10.png  1.png  2.png  3.png  4.png  5.png  6.png  7.png  8.png  9.png

[rsingh@rule51 TESTDIR]$ ls | awk -F. '{print $1}'
10
1
2
3
4
5
6
7
8
9
    
por 19.05.2016 / 03:00
1

Uma linha de shell simples (ksh, bash ou zsh; not dash):

set -- *.png; printf '%s\n' "${@%.png}"

Uma função simples (de No Extension):

ne(){ set -- *.png; printf '%s\n' "${@%.png}"; }

Ou uma função que remova qualquer extensão dada (png por padrão):

ne(){ ext=${1:-png}; set -- *."$ext"; printf '%s\n' "${@%.${ext}}"; }

Use como:

ne jpg

Se a saída for um asterisco * , não existe nenhum arquivo com essa extensão.

    
por 19.05.2016 / 09:13
0

Você pode tentar o seguinte feed awk a saída de seu supervisor é o "." e como todos os seus arquivos terão nome.png você imprime a primeira coluna: ls | awk -F"." '{print $1}'

    
por 13.06.2016 / 16:05
-1

Se você tem acesso ao sed, isso é melhor, pois tira a última extensão do arquivo, não importa o que seja (png, jpg, tiff, etc ...)

ls | sed -e 's/\..*$//'
    
por 18.05.2016 / 12:58

Tags