Como grep milhares de arquivos em um diretório para centenas de seqüências de caracteres em um arquivo


11

Estou tentando escrever uma grepdeclaração e isso está me matando. Também estou cansado de receber o arguments list too longerro. Eu tenho um arquivo, vamos chamá-lo subset.txt. Ele contém centenas de linhas com seqüências específicas, como MO43312948. No meu diretório de objetos, tenho milhares de arquivos e preciso copiar todos os arquivos que contêm as seqüências de caracteres listadas em subset.txtoutro diretório.

Eu estava tentando começar com isso para retornar os arquivos correspondentes do diretório de objetos.

grep -F "$(subset.txt)" /objects/*

Eu continuo recebendo `bash: / bin / grep: lista de argumentos muito longa``


6
Por que você colocou "$(subset.txt)"o comando assim? Isso é substituição de comando , o que fará com que seu shell seja executado subset.txt (como se fosse um comando ou script).
JigglyNaga

Respostas:


23

Você pode passar um diretório como destino para grepcom -Re um arquivo de padrões de entrada com -f:

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

Então, você está procurando:

grep -Ff subset.txt -r objects/

Você pode obter a lista de arquivos correspondentes com:

grep -Flf subset.txt -r objects/

Portanto, se sua lista final não for muito longa, você pode fazer:

 mv $(grep -Flf subset.txt -r objects/) new_dir/

Se isso retornar um argument list too longerro, use:

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

E se os nomes dos seus arquivos puderem conter espaços ou outros caracteres estranhos, use (assumindo o GNU grep):

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Por fim, se você deseja excluir arquivos binários, use:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

… Ou para evitar potencialmente milhares de mvchamadas com um argumento cada: ... | xargs -0 mv -t bar/(supondo que você mvsuporte a -topção).
David Foerster

11

usar

grep -F -f subset.txt 

para dizer ao grep para ler do subset.txtarquivo.

você pode usar o find para percorrer o arquivo.

find . -type f -exec grep -F -f subset.txt {} \;

ou

find . -type f -exec grep -F -f subset.txt {}  +

Alguma vantagem de usar em findvez de -routra que você faz filtragem adicional?
Phd

1
O @phk grep -rpesquisa em links simbólicos para arquivos regulares, o que pode ou não ser desejável (se eles apontam para dentro da mesma árvore, você está pesquisando o mesmo arquivo duas vezes; se eles apontam para fora, você está pesquisando um arquivo que pode ou não desejado).
Gilles 'SO- stop be evil'

As versões modernas de greptêm opções para controlar sua interação com links simbólicos ( man greppara determinar as especificidades do sistema atual). Uma recursiva grepserá muito mais rápida do que executada grepindividualmente em todos os arquivos via find.
Perry

1
@ Perry você tem certeza disso? Por quê? Além disso, observe que esta resposta está sendo usada -exec +, portanto, agrupará arquivos e não executará um grep por arquivo.
terdon

Eu corrijo, eu não tinha conhecimento das diferentes semânticas de -exec {} +vs -exec {} \;... você aprender algo novo todos os dias (eu ainda vejo nenhuma razão para que um único recursiva grepcostuma ser mais rápido do que múltipla greps correr a partir finddevido à criação e padrão processo de análise de sobrecarga, mas eu não tem números específicos à mão para fazer backup).
31416 Perry

3

Se você deseja acelerar ainda mais o grep, pode definir o código do idioma no seu shell antes de executá-lo, ou seja, use "LC_ALL = c". Isso será herdado no grep e desativará o processamento Unicode quando não for necessário e, em alguns casos, pode acelerar drasticamente o grep. Um ótimo blog que documenta isso pode ser encontrado em http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Esse truque também pode acelerar os scripts do shell bash, não apenas o grep.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.