ls -1
lista meus elementos assim:
foo.png
bar.png
foobar.png
...
Quero listado sem o seguinte .png
:
foo
bar
foobar
...
(o dir 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 estão listados sem a extensão. Quero criar um script que compare o arquivo de texto com a pasta para ver qual arquivo está faltando.
.
neles. Embora a convenção diz para nomear seus arquivos com.png
, no final, não há nenhuma razão para que eu não posso ter um arquivo PNG chamadofoo.zip
oumy.picture.20160518
ou apenasmypic
.ls
e canalizar a saída de ,ls
efind
principalmente devido à possibilidade de incorrer emnewline
, `tab char no nome do arquivo. Se o nome do arquivo forThe new art of working on .png\NEWLINE files and other formats
muitas, a solução proposta criará problemas.Respostas:
Você só precisa do shell para este trabalho.
POSIXly:
Com
zsh
:fonte
printf
;echo ${f%.png}
será suficiente.O
sed
comando remove (ou seja, substitui pela sequência vazia) qualquer sequência.png
encontrada no final de um nome de arquivo.O
.
é escapado da\.
maneira que é interpretado porsed
um.
caractere literal , e não pela expressão regular.
(que significa corresponder a qualquer caractere). O$
é a âncora de fim de linha, portanto não corresponde.png
ao meio de um nome de arquivo.fonte
sed 's/\.[^.]*$//'
-1
não é necessário, sendo o padrão aqui.-1
deve ser especificado. É apenas o padrão quando o pipe é ativado, o que é uma surpresa oculta para alguns. Tornar explícito ajuda a entender. Eu também faço isso nos meus scripts para saber que tipo de saída estou esperando..png
) antes de um caractere de nova linha, você apagará mesmo isso.png
e não apenas o último. É melhor evitar canalizar e analisar a saída de ls, pois reserva muitas surpresas bem escondidas ... (algumas palavras e referências mais na resposta).Se você quer apenas usar o bash:
Você deve
grep
procurar ao tentar encontrar correspondências, não para remover / substituir o quesed
é mais apropriado:Depois de decidir que precisa criar alguns subdiretórios para ordenar seus arquivos PNG, você pode facilmente mudar isso para:
fonte
find
canalizado parased
solução pode apresentar alguns problemas se você encontrar um arquivo com a chave (.png
) como parte do nome e pouco antes de um caractere de nova linha. É melhor evitar canalizar e analisar a saída de ,find
ouls
reserva muitas surpresas bem escondidas ... (algumas palavras e referências mais na resposta).find
por algo comoecho
no último exemplo. Não está claro qual propósitofind
serve lá e os resultados dependem da estrutura de diretório (ou seja, se você tem um diretóriofiles.png
)Eu iria
basename
(assumindo a implementação GNU):fonte
-z
(ou--zero
) para produzir saída separada por NUL (em vez de separada por nova linha).Outra resposta muito semelhante (estou surpreso que essa variante em particular ainda não tenha aparecido) é:
-1
opçãols
, poisls
assume que, se a saída padrão não for um terminal (neste caso, é um tubo).-n
opção parased
significa 'não imprimir a linha por padrão'/p
opção no final da substituição significa '... e imprima esta linha se uma substituição foi feita'.O efeito líquido disso é imprimir apenas as linhas que terminam
.png
com as.png
removidas. Ou seja, isso também atende à ligeira generalização da pergunta do OP, onde o diretório não contém apenas.png
arquivos.A
sed -n
técnica geralmente é útil nos casos em que você poderia usar grep + sed.fonte
.png
) antes do caractere de nova linha: nesse caso, você imprimirá essa parte sem png, não apagando apenas a última parte. Muitas vezes, é sugpugested para evitar a parse (e pipe) a saídals
porque os problemas podem ser escondidas apenas onde você não está pensando em ...find
ou - possivelmente melhor - use uma linguagem mais poderosa do quesh
para gerenciá-los (o fato de quesh
pode fazer tudo não significa que é a melhor escolha em cada caso). O shell foi projetado para usabilidade primeiro.ls
, mas está a caminho de problemas futuros. Muitas vezes, criamos scripts que usaremos mais tarde, quando já esqueceremos seu limite ... (é humano, é usual). Eu propus umfind
exemplo (com-exec
e sem tubo), mesmo que eu considere uma resposta melhor (porque pura concha) à resposta do tipo cuonglm , sólida e posix.locate
oumake
neles.Você pode usar apenas comandos BASH para fazer isso (sem nenhuma ferramenta externa).
Isso é útil quando você está sem o / usr / bin e funciona bem para nomes de arquivos como this.is.image.png e para todas as extensões.
fonte
Não é seguro analisar
ls
ou canalizarfind
[ 1 , 2 ]Não é seguro analisar (e canalizar) a saída
ls
oufind
, principalmente porque é possível encontrar nos nomes dos arquivos caracteres não usuais como a nova linha , a guia ... Aqui um ciclo de shell puro funcionará [ cuonglm ] .Mesmo o
find
comando não canalizado com a opção-exec
funcionará:Atualizações / Notas : Você pode
find .
pesquisar até os arquivos ocultos oufind ./*.png
obter apenas os não ocultos. Comfind *.png -exec ...
você pode ter problema no caso de estar presente um arquivo nomeado.png
porque o find irá obtê-lo como uma opção. Você pode adicionar-maxdepth 0
para evitar a descida nos diretórios nomeados comoDir_01.png
, oufind ./*.png -prune -exec ...
quando maxdepth não for permitido (obrigado Stéphane). Se você deseja evitar listar esses diretórios, adicione a opção-type f
(que também excluiria outros tipos de arquivos não regulares). Dê uma olhada noman
panorama mais completo sobre todas as opções disponíveis e lembre-se de verificar quando são compatíveis com POSIX, para uma melhor portabilidade.Algumas palavras mais
Pode acontecer, por exemplo, que, copiando o título de um documento e colando no nome do arquivo, uma ou mais novas linhas sejam finalizadas no próprio nome do arquivo. Podemos ser tão azarados que um título possa conter até a chave que precisamos usar antes de uma nova linha:
Se você deseja testar, pode criar nomes de arquivos como este com os comandos
O simples
/bin/ls *png
será exibido em?
vez dos caracteres não imprimíveisEm todos os casos em que você canalizará a saída de
ls
oufind
o seguinte comando terá nenhum indício de entender se a atual linha vem de um novo nome do arquivo ou se segue uma nova linha de caracteres no precedente nome do arquivo . Um nome desagradável , de fato, mas ainda legal.Um ciclo de shell com um parâmetro Parameter-Expansion,,
${parameter%word}
na variante comprintf
ouecho
irá funcionar ,, [ cuonglm ], [ Anthon1 ] .Na página de manual da expansão de parâmetros do shell [ 3 ]
fonte
find
comando são um pouco variável (por exemplo, se existe um diretório chamadofiles.png
)bash 4.3.11
, traço 0.5.7-4, zsh (quando necessário) 5.0.2. Sinta-se livre para ler este post que acrescenta algo mais. Concordo com a nota de canalizar a saídafind
, por isso sugeri expressamente-exec
e escrevi no título.:-)
.ls
não há problema algum quando a saída é canalizada ou redirecionada, mas, como mencionado no wiki, pode não funcionar para todos. A maioria só inserirá o?
lugar de caracteres especiais quando a saída for enviada ao terminal. ou seja, façaecho *.png | od -c
els *.png | od -c
. O problema da nova linha não é um problemals
, é um problema com qualquer comando que não termine nulo nos dois lados do canal.printf "${f%.png}\n"
está errado. O primeiro argumento é o formato, você não deve usar dados variáveis lá. Pode até ser visto como uma vulnerabilidade de DoS (tente com um%1000000000s.png
arquivo, por exemplo).find ./*.png -prune -exec...
ou você teria problemas com nomes começando com-
(e arquivos de tipo diretório, nota que-maxdepth
não é portátil)não foi o suficiente?
ou em geral, esse
irá remover todas as extensões
fonte
-1
não é necessário, sendo o padrão aqui.ls
faz de qualquer maneira sem essa opção quando sua saída não está sendo um terminal, como é o caso aqui.Use
rev
:rev
inverte todas as strings (linhas); você corta tudo depois do primeiro '.' e rev reverte o restante.Se você quiser
grep
'alma':fonte
-1
não é necessário, sendo o padrão aqui.My.2016.Summer.Vacation.png
cut -f 2-
.png
e uma nova linha logo após ... Sugere-se para evitar que analisarls
porque gostam de se esconder bem as surpresas ... :-)Se eu soubesse que o diretório tinha apenas arquivos com .png como uma extensão, eu teria acabado de executar:
ls | awk -F. '{print $1}'
Isso retornará o primeiro "campo" para qualquer coisa em que exista um nome de arquivo.extensão.
Exemplo:
fonte
.
, comoImage.1.png
e mesmo naqueles com nomes não agradáveis , com caracteres especiais. como a nova linha ou o que você vai usar como (entrada) separador de registro emawk
,RS
. Sugere-se evitar analisar als
saída, pois ela gosta de ocultar problemas que surgirão quando você não espera. Você pode ler mais nas referências 1 ou 2 . BTW agradável a idéia de usar awk ... Coloquei alguns exemplos em uma resposta..
para\.
dentrosed -e 's/\.png$//'
, mas isso se torna uma resposta que acabou de ser escrita. :-( note2 você pode tentar usarawk
algo comols | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}'
... mas você sempre terá o problema que o awk não pode saber se a linha está chegando está seguindo ou não uma nova linha dentro do nome do arquivo. Tentei dizer melhor na minha resposta .de acordo com o seu comentário "Eu tenho um arquivo de texto em que todos os nomes estão listados sem a extensão. Quero criar um script PHP que compare o arquivo de texto com a pasta para ver qual arquivo está faltando":
e o inverso:
fonte
ls -l | sed 's/\.png$//'
É o método mais preciso, conforme destacado por @roaima. Sem os fugitivos
\.png
arquivos nomeadosa_png.png
seriam listados como:a_
.fonte
ls -l
, como você faz, fornece detalhes do arquivo, não é sobre isso que o OP perguntou.Uma linha de shell simples (ksh, bash ou zsh; não traço):
Uma função simples (de No Extension):
Ou uma função que remove qualquer extensão fornecida (png por padrão):
Use como:
Se a saída for um asterisco
*
, não haverá arquivo com essa extensão.fonte
Você pode tentar o seguinte feed para ativar a saída de seu superator é o "." e como todos os seus arquivos terão name.png, você imprime a primeira coluna:
ls | awk -F"." '{print $1}'
fonte
Se você tiver acesso ao sed, é melhor, pois removerá a última extensão do arquivo, não importa qual seja (png, jpg, tiff, etc ...)
fonte
this.is.a.dotty.txt
. Tente ems/\.[^.]*$//
vez disso.