Eu tentei os dois comandos e o comando find | grep 'filename'
é muitas vezes mais lento que o find 'filename'
comando simples .
Qual seria uma explicação adequada para esse comportamento?
command-line
grep
find
search
file-search
yoyo_fun
fonte
fonte
time find "$HOME" -name '.profile'
relata mais tempo quetime find "$HOME" | grep -F '.profile'
. (17s vs. 12s).grep
variação corresponderá a qualquer lugar nofind
resultado, enquanto a correspondência comfind -name
somente corresponderá exatamente (neste caso).find filename
seria rápido . Eu meio que assumi que isso era um erro de digitação e que o OP significavafind -name filename
. Comfind filename
, apenasfilename
seria examinado (e nada mais).Respostas:
(Estou assumindo o GNU
find
aqui)Usando apenas
seria rápido, porque retornaria apenas
filename
, ou os nomes dentro,filename
se for um diretório, ou um erro se esse nome não existir no diretório atual. É uma operação muito rápida, semelhante als filename
(mas recursiva sefilename
for um diretório).Em contraste,
permitiria
find
gerar uma lista de todos os nomes do diretório atual e abaixo, quegrep
seriam filtrados. Obviamente, isso seria uma operação muito mais lenta.Estou assumindo que o que realmente era pretendido era
Seria
filename
o nome de um arquivo comum em qualquer lugar do diretório atual ou abaixo.Isso será tão rápido (ou comparativamente rápido) quanto
find | grep filename
, mas agrep
solução corresponderiafilename
ao caminho completo de cada nome encontrado, da mesma forma que-path '*filename*'
faria comfind
.A confusão vem de um mal-entendido de como
find
funciona.O utilitário usa vários caminhos e retorna todos os nomes abaixo desses caminhos.
Em seguida, você pode restringir os nomes retornados usando vários testes que podem atuar no nome do arquivo, no caminho, no registro de data e hora, no tamanho do arquivo, no tipo de arquivo etc.
Quando voce diz
você perguntar
find
para listar todos os nomes disponíveis sob as três caminhosa
,b
ec
. Se esses forem nomes de arquivos regulares no diretório atual, eles serão retornados. Se algum deles for o nome de um diretório, ele será retornado juntamente com todos os outros nomes dentro desse diretório.Quando eu faço
Isso gera uma lista de todos os nomes no diretório atual (
.
) e abaixo. Em seguida, restringe os nomes aos arquivos comuns, ou seja, não diretórios etc., com-type f
. Depois, há uma restrição adicional aos nomes que correspondem aofilename
uso-name 'filename'
. A stringfilename
pode ser um padrão globbing de nome de arquivo, como*.txt
(lembre-se de citá-la!).Exemplo:
O seguinte parece "encontrar" o arquivo chamado
.profile
no meu diretório pessoal:Mas, na verdade, apenas retorna todos os nomes no caminho
.profile
(existe apenas um nome e esse é o arquivo).Então
cd
subo um nível e tente novamente:O
find
comando agora não pode encontrar nenhum caminho chamado.profile
.No entanto, se eu procurar o diretório atual e restringir apenas os nomes retornados
.profile
, ele também será encontrado a partir daí:fonte
find filename
só iria voltarfilename
sefilename
não era do tipo diretório (ou era do tipo diretório, mas não tem qualquer entrada própria)Explicação não técnica: Procurar por Jack na multidão é mais rápido do que procurar todos na multidão e eliminar tudo da consideração, exceto Jack.
fonte
find jack
listarájack
se é um arquivo chamadojack
ou todos os nomes no diretório, se for um diretório. É um mal-entendido de comofind
funciona.Ainda não entendi o problema, mas posso fornecer mais algumas idéias.
Como para Kusalananda, a
find | grep
ligação é claramente mais rápida no meu sistema, o que não faz muito sentido. No começo, assumi algum tipo de problema de buffer; essa gravação no console diminui o tempo para o próximo syscall para ler o próximo nome de arquivo. A gravação em um pipe é muito rápida: cerca de 40MiB / s, mesmo para gravações de 32 bytes (no meu sistema bastante lento; 300 MiB / s, para um tamanho de bloco de 1MiB). Portanto, presumi quefind
fosse possível ler o sistema de arquivos mais rapidamente ao gravar em um canal (ou arquivo), para que as duas operações que leem os caminhos do arquivo e gravem no console possam ser executadas em paralelo (o que,find
como um processo de encadeamento único, não pode ser feito sozinho).É
find
culpaComparando as duas chamadas
e
mostra que
find
faz algo incrivelmente estúpido (seja lá o que for). Isso acaba sendo bastante incompetente na execução-name '*.txt'
.Pode depender da proporção de entrada / saída
Você pode pensar que
find -name
ganha se houver muito pouco para escrever. Mas isso só fica mais embaraçosofind
. Ele perde, mesmo que não haja nada para gravar em arquivos de 200K (13 milhões de dados de canal) paragrep
:find
pode ser tão rápido quantogrep
, emboraAcontece que essa
find
estupidez comname
não se estende a outros testes. Use uma regex e o problema se foi:Eu acho que isso pode ser considerado um bug. Alguém disposto a registrar um relatório de bug? Minha versão é find (GNU findutils) 4.6.0
fonte
-name
teste primeiro, pode ter sido mais lento devido ao conteúdo do diretório não estar em cache. (Ao testar-name
e-regex
acho que eles levam aproximadamente ao mesmo tempo, pelo menos uma vez o efeito cache foi levado em consideração Claro que pode ser apenas uma versão diferente.find
...)find
versão é find (GNU findutils) 4.6.0-name '*.txt'
diminuafind
? Ele precisa fazer um trabalho extra, testando cada nome de arquivo.find
tem que escrever menos dados. E escrever em um tubo é uma operação muito mais lenta./dev/null
usar de alguma forma menos tempo do sistema.Aviso : Suponho que você queira dizer
find . -name filename
(caso contrário, você está procurando coisas diferentes;find filename
na verdade, procura um caminho chamado nome do arquivo , que pode conter quase nenhum arquivo e, portanto, sair rapidamente).Suponha que você tenha um diretório com cinco mil arquivos. Na maioria dos sistemas de arquivos, esses arquivos são realmente armazenados em uma estrutura em árvore , o que permite localizar rapidamente qualquer arquivo.
Então, quando você perguntar
find
para localizar um arquivo cujo nome só exige a verificação,find
irá pedir para que arquivo, e somente esse arquivo, para o sistema de arquivos subjacente, que irá ler muito poucas páginas a partir do armazenamento em massa. Portanto, se o sistema de arquivos valer a pena, essa operação será executada muito mais rápido do que percorrer a árvore inteira para recuperar todas as entradas.Quando você pede algo simples,
find
no entanto, é exatamente isso que você faz, percorre a árvore inteira, lendo. Cada. Solteiro. Entrada. Com diretórios grandes, isso pode ser um problema (é exatamente o motivo pelo qual vários softwares, que precisam armazenar muitos arquivos em disco, criarão "árvores de diretório" com dois ou três componentes de profundidade: dessa forma, cada folha precisa conter apenas menos arquivos).fonte
Vamos supor que o arquivo / john / paul / george / ringo / beatles exista e o arquivo que você está procurando seja chamado de 'stones'
find irá comparar 'beatles' com 'stones' e soltá-lo quando os 's' e 'b' não coincidirem.
Nesse caso, o find passará '/ john / paul / george / ringo / beatles' para grep e o grep terá que percorrer todo o caminho antes de determinar se é uma correspondência.
O grep está, portanto, fazendo muito mais trabalho e é por isso que leva mais tempo
fonte