find e grep pipeline não retornando nada

2

Eu tenho arquivos chamados lect1.txt , lect2.doc e lect3.doc .

Eu quero obter um arquivo que é um arquivo .txt e contém lect como o nome do arquivo.

Eu tentei

find *.txt | grep lect*

e não retornou nada.

mas quando eu fiz

find *.txt | grep "lect*"

retornou lect1.txt .

Qual é a diferença entre essas duas expressões?

    
por March3April4 26.03.2015 / 18:17

3 respostas

6

grep procura o primeiro argumento (o padrão) nos arquivos transmitidos na linha de comando ou stdin se nenhum arquivo for passado.

Sem a cota, seu shell expandirá lect* para todos os arquivos no diretório que começam com lect . Seu comando será então:

grep lect1.txt lect2.doc lect3.doc

, o que significa que procura o texto lect1.txt nos dois .doc arquivos . A menos que um dos arquivos .doc tenha a frase lect1.txt , ele não retornará nada. Para ser mais preciso, ele procurará lect1 seguido por qualquer caractere (o . ) seguido por txt , então também encontrará lect1-txt e lect1xtxt etc)

Em seu segundo exemplo, você citou "lect.*" para que o shell não o expanda e seja passado como é para grep . Com apenas um padrão passado como argumento, grep pesquisará os nomes de arquivos passados em stdin para o padrão, que é o que você é depois que eu acredito.

    
por 26.03.2015 / 18:27
1

find *.txt | grep lect*

Você geralmente deseja fornecer um nome de caminho como o primeiro argumento para find(1) , em vez de um nome de arquivo. Certamente não é um padrão de nome de arquivo. O shell está expandindo *.txt para o nome de todos os arquivos *.txt no diretório atual antes de chamar find , que não é o que você deseja aqui.

Mais variantes úteis desse comando são

find . -name 'lect*' | grep 'txt$'

ou

find . -name 'lect*txt'

Além disso, observe que find(1) usa glob expressões em -name primários, enquanto grep(1) usa expressões regulares . Isso é importante aqui porque * significa algo um pouco diferente nos dois sistemas.

As implementações do BSD e do GNU de find têm o -regex primary não padrão, o que permite usar expressões regulares:

find . -regex '.*/lect.*txt'

Observe que o padrão deve corresponder ao caminho inteiro encontrado por find , e é por isso que precisamos do prefixo .*/ e não é necessário fixar o txt no termine com $ como com grep .

    
por 26.03.2015 / 18:26
1

Você está usando indevidamente find e está funcionando acidentalmente. Você vê - executando:

find *.txt 

O que você está realmente fazendo é invocar:

find lect1.txt

E você está realizando pouco mais de echo . Se, no entanto, você executar encontrar com um critério de pesquisa - por exemplo:

find . -name '*.txt'

Em seguida, ele percorrerá o diretório atual . e imprimirá qualquer nome de arquivo correspondente à especificação em qualquer subdiretório.

Cuidado deve ser tomado, porque o '*' como interpretado por find, o * no shell e o * em uma expressão regular regular diferem em significado.

Se você for grep ing * significa 'zero ou mais instâncias do caractere precedente.

Então você está realmente:

  • ecoando todos os seus nomes de arquivo (globbing *.txt ).
  • grepping para imprimir qualquer que corresponda a qualquer caractere com lec , lect , lectt , lecttttttt etc. no meio.

No seu primeiro exemplo, você não está chegando tão longe - o shell está expandindo seu padrão, então, na verdade, está procurando por algo que corresponda a echo lect* - que pode funcionar acidentalmente, porque você tem um arquivo em seu diretório que se expande apropriadamente, mas não está fazendo o que você pretendia.

Eu gostaria de sugerir que o que você quer é:

find . -name 'lect*.txt' -print
    
por 26.03.2015 / 18:30

Tags