Pergunta

Eu não entendo muito bem o exemplo dado do man find, alguém pode me dar alguns exemplos e explicações? Posso combinar expressão regular nele?


A pergunta mais detalhada é assim:

Escreva um script de shell, changeall, que tem uma interface como changeall [-r|-R] "string1" "string2". Ele encontrará todos os arquivos com um sufixo de .h, .C, .cc, ou .cpp e mudar todas as ocorrências de string1 para string2. -r é opção para permanecer apenas no diretor atual ou incluir o subdir.

NOTA:

  1. Para um caso não recursivo, ls não é permitido, só podíamos usar find e sed.
  2. eu tentei find -depth Mas não foi apoiado. É por isso que eu estava me perguntando se -prune poderia ajudar, mas não entendeu o exemplo de man find.

EDIT2: Eu estava fazendo tarefas, não fiz perguntas em ótimos detalhes porque gostaria de terminar sozinho. Desde que eu já fiz isso e entregue, agora posso declarar toda a questão. Além disso, consegui terminar a tarefa sem usar -prune, mas gostaria de aprender de qualquer maneira.

Foi útil?

Solução

O que eu achei confuso sobre -prune é isso é uma ação (como -print), não um teste (como -name). Altera a lista de "tarefas", mas sempre retorna verdadeiro.

O padrão geral para usar -prune é isto:

find [path] [conditions to prune] -prune -o \
            [your usual conditions] [actions to perform]

Você praticamente sempre quer o -o (lógico ou) imediatamente após -prune, porque a primeira parte do teste (até e incluindo -prune) retornará falso Para as coisas que você realmente deseja (ou seja: as coisas que você não quer podar).

Aqui está um exemplo:

find . -name .snapshot -prune -o -name '*.foo' -print

Isso encontrará os arquivos "*.foo" que não estão em diretórios .snapshot ". Neste exemplo, -name .snapshot compõe o [conditions to prune], e -name '*.foo' -print é [your usual conditions] e [actions to perform].

Anotações importantes:

  1. Se tudo o que você deseja fazer é imprimir os resultados que você pode estar acostumado a deixar de fora o -print ação. Você geralmente não quero fazer isso ao usar -prune.

    O comportamento padrão do encontro é "e" o inteira expressão com o -print ação se não houver outras ações senão -prune (Ironicamente) no final. Isso significa que escrever isso:

    find . -name .snapshot -prune -o -name '*.foo'              # DON'T DO THIS
    

    é equivalente a escrever isso:

    find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
    

    O que significa que também imprimirá o nome do diretório que você está podando, o que geralmente não é o que você deseja. Em vez disso, é melhor especificar explicitamente o -print ação se é isso que você deseja:

    find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. Se a sua "condição usual" corresponder aos arquivos que também correspondem à sua condição de ameixa, esses arquivos irão não ser incluído na saída. A maneira de consertar isso é adicionar um -type d predicar à sua condição de ameixa.

    Por exemplo, suponha que queríamos podar qualquer diretório que começou com .git (Isso é reconhecidamente um tanto artificial - normalmente você só precisa remover a coisa nomeada exatamente .git), mas, além disso, queria ver todos os arquivos, incluindo arquivos como .gitignore. Você pode tentar o seguinte:

    find . -name '.git*' -prune -o -type f -print               # DON'T DO THIS
    

    Isso seria não incluir .gitignore na saída. Aqui está a versão fixa:

    find . -type d -name '.git*' -prune -o -type f -print       # DO THIS
    

Dica extra: se você está usando a versão GNU de find, a página do Texinfo para find tem uma explicação mais detalhada do que sua manpra (como é verdadeira para a maioria dos utilitários da GNU).

Outras dicas

Cuidado que -Rune não impede descer em algum diretório como alguns disseram. Isso evita descer em diretórios que correspondem ao teste ao qual é aplicado. Talvez alguns exemplos ajudem (consulte o fundo para um exemplo regex). Desculpe por isso ser tão demorado.

$ find . -printf "%y %p\n"    # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh

$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test

$ find . -prune
.

$ find . -name test -prune
./test
./dir1/test
./dir2/test

$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl

$ find . -name test -prune -regex ".*/my.*p.$"
(no results)

$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test

$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py

$ find . -not -regex ".*test.*"                   .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

Normalmente, da maneira nativa, fazemos as coisas no Linux e a maneira como pensamos ser da esquerda para a direita.
Então você iria escrever o que está procurando primeiro:

find / -name "*.php"

Então você provavelmente pressiona Enter e percebe que está recebendo muitos arquivos de diretórios que deseja não. Vamos excluir /mídia para evitar pesquisar suas unidades montadas.
Agora você deve apenas anexar o seguinte ao comando anterior:

-print -o -path '/media' -prune

Então, o comando final é:

find / -name "*.php" -print -o -path '/media' -prune

............... | <--- incluir ---> | .................... | <- -------- exclude ---------> |

Eu acho que essa estrutura é muito mais fácil e se correlaciona com a abordagem correta

Adicionando aos conselhos dados em outras respostas (não tenho representante para criar respostas) ...

Ao combinar -prune Com outras expressões, há uma diferença sutil de comportamento, dependendo de quais outras expressões são usadas.

O exemplo do @Laurence Gonsalves encontrará os arquivos "*.foo" que não estão abaixo ".snapshot" Diretórios:-

find . -name .snapshot -prune -o -name '*.foo' -print

No entanto, essa mão curta ligeiramente diferente, talvez inadvertidamente, também listará o .snapshot Diretório (e qualquer diretório .SNAPSHOT aninhado):-

find . -name .snapshot -prune -o -name '*.foo'

O motivo é (de acordo com a manpra no meu sistema):-

Se a expressão dada não contiver nenhuma das primárias -exec, -ls, -ok ou -print, a expressão dada é efetivamente substituída por:

(dado_expression) -print

Ou seja, o segundo exemplo é o equivalente a entrar no seguinte, modificando assim o agrupamento de termos:-

find . \( -name .snapshot -prune -o -name '*.foo' \) -print

Isso foi visto pelo menos no Solaris 5.10. Tendo usado vários sabores de *nix por aproximadamente 10 anos, procurei recentemente por um motivo pelo qual isso ocorre.

Prune é um não recurso em nenhum interruptor de diretório.

Da página do homem

Se -profundidade não é dada, verdadeira; Se o arquivo for um diretório, não desça nele. Se a profundidade é dada, falsa; Sem efeito.

Basicamente, ele não será despertado em nenhum diretório.

Veja este exemplo:

Você tem os seguintes diretórios

  • /home/test2
  • /home/test2/test2

Se você correr find -name test2:

Ele retornará os dois diretórios

Se você correr find -name test2 -prune:

Ele retornará apenas/home/test2, pois não descerá para/home/test2 para encontrar/home/test2/test2

Não sou especialista nisso (e esta página foi muito útil junto com http://mywiki.wooledge.org/usingfind)

Acabei de perceber -path é para um caminho que Combina totalmente a string/caminho que vem logo depois find (. em esses exemplos) onde -name corresponde a todos os nomes de base.

find . -path ./.git  -prune -o -name file  -print

bloqueia o diretório .git em seu diretório atual ( Como sua descoberta em . )

find . -name .git  -prune -o -name file  -print

Bloqueia todos os subdiretos .git recursivamente.

Note o ./ é extremamente importante !! -path deve corresponder a um caminho ancorado a . ou o que vier logo após encontrar Se você conseguir partidas sem isso (do outro lado da AR '-o') Provavelmente não está sendo podado! Eu não tinha conhecimento disso e me colocou de usar -Path quando é ótimo quando você não quer podar todo o subdiretório com o mesmo nome de base: D

Mostre tudo, incluindo Dir em si, mas não seu longo conteúdo chato:

find . -print -name dir -prune

Se você ler todas as boas respostas aqui, meu entendimento agora é que o seguinte retornará os mesmos resultados:

find . -path ./dir1\*  -prune -o -print

find . -path ./dir1  -prune -o -print

find . -path ./dir1\*  -o -print
#look no prune at all!

Mas O último levará muito mais tempo, pois ainda procura tudo no DIR1. Eu acho que a verdadeira questão é como -or Resultados indesejados sem realmente pesquisá -los.

Então eu acho que ameixa significa não decentes partidas anteriores, mas marque como feito ...

http://www.gnu.org/software/findutils/manual/html_mono/find.html"No entanto, isso não se deve ao efeito da ação '-Prune' (que apenas impede a descida adicional, não garante que ignoremos esse item). Em vez disso, esse efeito se deve ao uso de '-o'. Como o lado esquerdo da condição "ou" foi bem-sucedido para ./src/emacs, não é necessário avaliar o lado direito ('-Print') para esse arquivo específico ".

find cria uma lista de arquivos. Aplica o predicado que você forneceu a cada um e retorna aqueles que passam.

Essa ideia é isso -prune significa que a exclusão dos resultados foi realmente confusa para mim. Você pode excluir um arquivo sem ameixa:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

Tudo -prune Faz é alterar o comportamento da pesquisa. Se a partida atual for um diretório, diz "Ei find, aquele arquivo que você acabou de combinar, não desce nele ". Ele apenas remove essa árvore (mas não o próprio arquivo) da lista de arquivos para pesquisar.

Deve ser nomeado -dont-descend.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top