Estou tentando executar um find
comando para todos os arquivos JavaScript, mas como excluo um diretório específico?
Aqui está o find
código que estamos usando.
for file in $(find . -name '*.js')
do
java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
find ... | while read -r file ...
. Além disso, é melhor aceitar e aprovar respostas.for file in $(find .); do echo "$file"; done
. Nomes com espaços são divididos, o que não queremos.Respostas:
Use o
-prune
interruptor. Por exemplo, se você deseja excluir omisc
diretório, adicione a-path ./misc -prune -o
ao seu comando find:Aqui está um exemplo com vários diretórios:
Aqui nós excluímos dir1 , dir2 e dir3 , pois nas
find
expressões é uma ação que age com base nos critérios-path dir1 -o -path dir2 -o -path dir3
(se dir1 ou dir2 ou dir3 ), ANDed withtype -d
.Outra ação é
-o print
apenas imprimir.fonte
-print
(ou qualquer outra ação) explicitamente depois-name
. Nesse caso, os dois "lados" da-o
impressão acabam, enquanto que, se você usar-print
, apenas esse lado é impresso.Because -delete implies -depth, you cannot usefully use -prune and -delete together.
Então, como faço para excluir com o find se quero excluir diretórios específicos da exclusão?find . -not -path "./.git*"
. Usar em./dir*
vez de./dir/*
remove o diretório e o conteúdo da saída.Se
-prune
não funcionar para você, isso irá:Advertência: requer percorrer todos os diretórios indesejados.
fonte
-prune
não exclui o diretório em si, exclui seu conteúdo, o que significa que você obterá uma linha indesejada na saída com o diretório excluído..
para*
. portantofind -name "*.js" -not -path "*/omitme/*"
, omitiria arquivos de um diretório chamado "omitme" em qualquer nível de profundidade.-print
explicitamente.Acho que é mais fácil raciocinar a seguir do que outras soluções propostas:
Nota importante: os caminhos digitados depois
-path
devem corresponder exatamente ao quefind
seria impresso sem a exclusão. Se esta frase confunde apenas certifique-se de usar caminhos completos através do todo comando como este: . Veja a nota [1] se você quiser entender melhor.find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
Por dentro
\(
e\)
é uma expressão que corresponderá exatamentebuild/external
(veja a nota importante acima) e, com sucesso, evitará atravessar qualquer coisa abaixo . Isso é então agrupado como uma única expressão com parênteses escapados e prefixado com o-not
qual fará com quefind
pule qualquer coisa que corresponda a essa expressão.Pode-se perguntar se a adição
-not
não fará com que todos os outros arquivos ocultos-prune
reapareçam, e a resposta é não. A maneira como-prune
funciona é que tudo o que, uma vez alcançado, os arquivos abaixo desse diretório são permanentemente ignorados.Isso vem de um caso de uso real, no qual eu precisava chamar o yui-compressor em alguns arquivos gerados pelo wintersmith, mas deixar de fora outros arquivos que precisam ser enviados como estão.
Nota [1] : Se você deseja excluir
/tmp/foo/bar
e executar o find como este "find /tmp \(...
", deverá especificar-path /tmp/foo/bar
. Se, por outro lado, você executar encontrar assimcd /tmp; find . \(...
, deverá especificar-path ./foo/bar
.fonte
find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
-exec rm -rf {} \;
vez de-delete
.find
, isso é óbvio, na verdade, mas me deixou de fora. Se você está procurando no diretório atual (especificando.
como o caminho de pesquisa, ou não especificar um em tudo), você provavelmente vai querer o seu padrão depois-path
de começar com./
, por exemplo:find -not \( -path ./.git -prune \) -type f
.find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)
seguida de quaisquer condições que devem corresponder ao que você está procurando.Há claramente alguma confusão aqui sobre qual deveria ser a sintaxe preferida para ignorar um diretório.
Opinião GNU
Na página de manual do GNU find
Raciocínio
-prune
párafind
de descer para um diretório. Apenas especificar-not -path
continuará no diretório ignorado , mas-not -path
será falso sempre quefind
testar cada arquivo.Problemas com
-prune
-prune
faz o que se destina, mas ainda há algumas coisas que você precisa cuidar ao usá-lo.find
imprime o diretório removido.-prune
só funciona com-print
e sem outras ações.-prune
funciona com qualquer ação, exceto-delete
. Por que não funciona com exclusão? Para-delete
funcionar, encontre as necessidades de percorrer o diretório na ordem DFS, já-delete
que primeiro excluirá as folhas, depois os pais das folhas, etc ... Mas, para especificar-prune
que faz sentido, éfind
necessário acessar um diretório e parar de descer, claramente não faz sentido com-depth
ou-delete
ligado.atuação
Configurei um teste simples das três principais respostas votadas para essa pergunta (substituídas
-print
por-exec bash -c 'echo $0' {} \;
para mostrar outro exemplo de ação). Os resultados estão abaixoConclusão
Ambos sintaxe do f10bit e sintaxe de Daniel C. Sobral tomou 10-25ms para executar em média. A sintaxe do GetFree , que não usa
-prune
, levou 865ms. Portanto, sim, este é um exemplo bastante extremo, mas se você se importa com o tempo de execução e está fazendo algo intensamente remotamente, deve usá-lo-prune
.Observe que a sintaxe de Daniel C. Sobral apresentou o melhor das duas
-prune
sintaxes; mas suspeito fortemente que esse seja o resultado de algum cache, pois a troca da ordem em que os dois foram executados resultou no resultado oposto, enquanto a versão sem remoção foi sempre mais lenta.Script de teste
fonte
-prune
, posso dizer que raramente há diferença. Tenha em mente que o comando começar a primeira irá beneficiar o desempenho da CPU, o mais tarde cpu aquecer> queda de desempenho causa menor devagar (eu fiz cache de purga antes de cada comando como sugestão @ndemou)name1() name2() name3()
no script de teste do @BroSlow acima para alterar a ordem de execução e obter um visual do que eu disse. Na vida real, é imperceptível entre os dois.Este é o único que funcionou para mim.
Procurando por "MyFile" excluindo "Diretório". Dê ênfase às estrelas *.
fonte
! -path '*/Directory/*'
ao seu comando em sucessão a ignorar vários diretóriosdocker container
só funciona comsh -c "find..."
Uma opção seria excluir todos os resultados que contêm o nome do diretório com grep. Por exemplo:
fonte
-prune
) - não.find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3
mas pode haver uma maneira grep.egrep -v '(dir1|dir2|dir3)'
. No entanto, neste estudo de caso específico, seria melhor excluir diretórios dentro defind
si.Eu prefiro a
-not
notação ... é mais legível:fonte
find
diz: "Para ignorar um diretório e os arquivos nele, use -prune".find . -iname '*' -and -not -path './somePath'
não impede que ele entre no referido diretório.find . -iname '*' -not -path './.git/*'
find . -not -path "*/.git*"
seria o que você deseja.Use a opção -prune. Então, algo como:
O '-type d -name proc -prune' procura apenas os diretórios chamados proc para excluir.
O '-o' é um operador 'OR'.
fonte
-print
ao final pode melhorar os resultados.find . -type d -name .hg -prune -o -name data
ignorou o conteúdo dos.hg
diretórios (múltiplos) , mas listou os.hg
próprios diretórios. Com-print
, ele listou apenas os diretórios "dados" que eu estava procurando.-prune
definitivamente funciona e é a melhor resposta, pois impede a descida no diretório que você deseja excluir.-not -path
que ainda pesquisa o diretório excluído, simplesmente não imprime o resultado, o que pode ser um problema se o diretório excluído estiver montado no volume da rede ou se você não tiver permissões.A parte complicada é que
find
é muito particular a ordem dos argumentos; portanto, se você não os acertar, seu comando pode não funcionar. A ordem dos argumentos é geralmente a seguinte:{path}
: Coloque todos os argumentos relacionados ao caminho primeiro, como. -path './dir1' -prune -o
{options}
: Eu tenho mais sucesso ao colocar-name, -iname, etc
como a última opção neste grupo. Por exemplo-type f -iname '*.js'
{action}
: Você deseja adicionar-print
ao usar-prune
Aqui está um exemplo de trabalho:
fonte
Este é o formato que eu usei para excluir alguns caminhos:
Eu usei isso para encontrar todos os arquivos que não estão nos caminhos ". *":
fonte
A abordagem -path -prune também funciona com curingas no caminho. Aqui está uma instrução find que encontrará os diretórios de um servidor git que atende a vários repositórios git, deixando de fora os diretórios internos do git:
fonte
Para excluir vários diretórios:
Para adicionar diretórios, adicione
-o -path "./dirname/*"
:Mas talvez você deva usar uma expressão regular , se houver muitos diretórios a serem excluídos.
fonte
Há muitas respostas boas, levei algum tempo para entender para que serviam cada elemento do comando e a lógica por trás dele.
find começará a encontrar arquivos e diretórios no diretório atual, daí o
find .
.A
-o
opção representa um OR lógico e separa as duas partes do comando:Qualquer diretório ou arquivo que não seja o diretório ./misc não passará no primeiro teste
-path ./misc
. Mas eles serão testados contra a segunda expressão. Se o nome deles corresponder ao padrão,*.txt
eles serão impressos, devido ao-print
opção.Quando a localização atinge o diretório ./misc, esse diretório satisfaz apenas a primeira expressão. Portanto, a
-prune
opção será aplicada a ele. Diz ao comando find para não explorar esse diretório. Portanto, qualquer arquivo ou diretório em ./misc nem será explorado pelo find, não será testado na segunda parte da expressão e não será impresso.fonte
Para uma solução funcional (testada no Ubuntu 12.04 (Precise Pangolin)) ...
procurará por arquivos MP3 na pasta e nas subpastas atuais, exceto na subpasta dir1.
Usar:
... para excluir dir1 AND dir2
fonte
um bom truque para evitar a impressão dos diretórios removidos é usar
-print
(também funciona-exec
) depois do lado direito do-or
depois-prune
. Por exemplo, ...imprimirá o caminho de todos os arquivos abaixo do diretório atual com a extensão `.j2", ignorando todos os diretórios ocultos. Limpo. Mas também imprimirá o caminho completo de cada diretório que estiver sendo ignorado, conforme observado acima. a seguir não, ...
porque logicamente há um oculto
-and
após o-iname
operador e antes da impressão. Isso o vincula à parte correta da-or
cláusula devido à ordem booleana de operações e associatividade. Mas os documentos dizem que há um oculto-print
se ele (ou qualquer um de seus primos ...-print0
, etc) não for especificado. Então, por que a parte esquerda da-or
impressão não está? Aparentemente (e eu não entendi isso desde a primeira leitura da página de manual), isso é verdade se não houver apenas operadores descritivos aparentemente não faria nada, então acho que faz sentido. Como mencionado acima, tudo isso também funciona ; portanto, a seguir, é exibida uma lista completa de cada arquivo com a extensão desejada, mas não listando o primeiro nível de cada diretório oculto, ...-print
- ou-exec
EM QUALQUER LUGAR, nesse caso, - a impressão é logicamente espalhada em torno de tal forma que tudo seja impresso. Se mesmo UMprint
operação no estilo - é expressa em qualquer cláusula, todas essas lógicas ocultas desaparecem e você obtém apenas o que deseja. especificamos. Agora, francamente, eu poderia ter preferido o contrário, mas então umfind
-exec
ls -la
Para mim (e outras pessoas neste segmento), a
find
sintaxe fica bem barroca muito rapidamente, então eu sempre uso parênteses para ter certeza de que sei o que se liga ao que, então eu geralmente crio uma macro para capacidade de digitação e forma todas as declarações como. ..É difícil dar errado, configurando o mundo em duas partes dessa maneira. Espero que isso ajude, embora pareça improvável que alguém leia até a 30ª resposta e vote, mas pode-se esperar. :-)
fonte
Você pode usar a opção de remoção para conseguir isso. Como por exemplo:
Ou a opção inversa grep "grep -v":
Você pode encontrar instruções e exemplos detalhados no comando Linux find, excluindo diretórios da pesquisa .
fonte
find . -type f -print -o -path "*/node_modules" -prune
usar ... o caractere curinga que ignora "node_modules" em qualquer nível; o uso-print
na primeira alternativa-type f -print
faz com que apenas essa parte seja impressa, portanto os diretórios "node_modules" não são listados. (que pode também ser invertida:find . -path "*/node_modules" -prune -o -type f -print
)./node_modules
e usar*/node_modules
. No meu caso, ondenode_modules
existe apenas no diretório em que inicio a pesquisa (e nessenode_modules
diretório), posso usá-lofind . -type f -print -o -path "./node_modules" -prune
porque não haverá umnode_modules
diretório em nenhum outro diretório.node_modules
subdiretório, mas também havia subdiretórios que tinham seus próprios node_modules ... usando./node_modules
correspondências apenas ao subdiretórionode_modules
no diretório atual.
e removendo-o; usar*/node_modules
corresponde e remove o diretório a qualquer profundidade, porque o*
as glob corresponde a qualquer prefixo do caminho inicial, como./test5/main/node_modules
, não apenas o./
prefixo. O*
é um curinga, mas como um glob não como um regex.fonte
find ~/Projects -name '*.js' -\! -name 'node_modules' -prune
ainda está transformando-se arquivos comnode_modules
em seu caminhofind ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print
. O nome desse caminho deve corresponder exatamente ao que a impressão seria impressa para imprimir o diretório.parece funcionar da mesma forma que
e é mais fácil lembrar da IMO.
fonte
TLDR: entenda seus diretórios raiz e adapte sua pesquisa a partir daí, usando a
-path <excluded_path> -prune -o
opção Não inclua um final/
no final do caminho excluído.Exemplo:
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
Para usar efetivamente o
find
, acredito que é imperativo ter um bom entendimento da estrutura de diretórios do sistema de arquivos. No meu computador doméstico, eu tenho discos rígidos com vários TB, com cerca de metade desse conteúdo sendo copiada usandorsnapshot
(ou seja,rsync
). Embora faça backup em uma unidade fisicamente independente (duplicada), ela é montada no/
diretório raiz ( ) do meu sistema/mnt/Backups/rsnapshot_backups/
::O
/mnt/Backups/rsnapshot_backups/
diretório atualmente ocupa ~ 2,9 TB, com ~ 60M de arquivos e pastas; simplesmente atravessar esses conteúdos leva tempo:Assim, sempre que eu precisar procurar um arquivo na minha
/
partição (raiz), preciso lidar com (evitar se possível) atravessar minha partição de backups.EXEMPLOS
Entre as abordagens sugeridas de várias maneiras neste tópico ( Como excluir um diretório no comando find. ), Acho que as pesquisas usando a resposta aceita são muito mais rápidas - com ressalvas.
Solução 1
Digamos que desejo encontrar o arquivo do sistema
libname-server-2.a
, mas não desejo pesquisar nos meusrsnapshot
backups. Para localizar rapidamente um arquivo do sistema, use o caminho de exclusão/mnt
(por exemplo, use/mnt
, not/mnt/
, ou/mnt/Backups
, ou ...):... encontra esse arquivo em apenas alguns segundos, enquanto isso leva muito mais tempo (parecendo ser repetido em todos os diretórios "excluídos"):
Solução 2
A outra solução oferecida neste segmento ( SO # 4210042 ) também apresenta desempenho ruim:
RESUMO CONCLUSÕES
Use a abordagem ilustrada em " Solução 1 "
ie
observando que sempre que você adiciona a
/
trilha ao caminho excluído, ofind
comando entra recursivamente nos/mnt/*
diretórios (todos esses) - que, no meu caso, por causa dos/mnt/Backups/rsnapshot_backups/*
subdiretórios, inclui adicionalmente ~ 2,9 TB de arquivos a serem pesquisados! Ao não anexar uma trilha,/
a pesquisa deve ser concluída quase imediatamente (em segundos).A "Solução 2" (
... -not -path <exclude path> ...
) também parece procurar recursivamente os diretórios excluídos - não retornando correspondências excluídas, mas consumindo desnecessariamente esse tempo de pesquisa.Pesquisando nesses
rsnapshot
backups:Para localizar um arquivo em um dos meus
rsnapshot
backups horários / diários / semanais / mensais ):Excluindo um diretório aninhado:
Aqui, quero excluir um diretório aninhado, por exemplo,
/mnt/Vancouver/projects/ie/claws/data/*
ao pesquisar em/mnt/Vancouver/projects/
:Além: A adição
-print
no final do comando suprime a impressão do diretório excluído:fonte
find
, é o número de entradas de diretório que ele deve examinar. Portanto, é muito pior se você tiver muitos, muitos arquivos pequenos (especialmente se todos estiverem multiplamente vinculados!) Do que se você tiver apenas um punhado de arquivos com vários gigabytes.sudo ls -R / | wc -l
indica ~ 76,5 milhões de arquivos (a maioria dos quais é copiada, exceto arquivos de sistema "não configurados");/mnt/Vancouver/
comls -R | wc -l
indica ~ 2.35M arquivos;/home/victoria/
contém 0,668 milhões de arquivos.Você também pode usar expressões regulares para incluir / excluir alguns arquivos / direcionar sua pesquisa usando algo como isto:
Isso fornecerá apenas todos os arquivos js, vue, css, etc, mas excluindo todos os arquivos nas pastas
node_modules
evendor
.fonte
Eu estava usando
find
para fornecer uma lista de arquivosxgettext
e queria omitir um diretório específico e seu conteúdo. Eu tentei muitas permutações de-path
combinado com,-prune
mas foi incapaz de excluir completamente o diretório que eu queria ir.Embora eu tenha conseguido ignorar o conteúdo do diretório que eu queria ignorar,
find
retornei o próprio diretório como um dos resultados, o que causouxgettext
uma falha como resultado (não aceita diretórios; apenas arquivos).Minha solução foi simplesmente usar
grep -v
para pular o diretório que eu não queria nos resultados:Se existe ou não um argumento para
find
isso funcionará 100%, não posso dizer com certeza. O usogrep
foi uma solução rápida e fácil após algumas dores de cabeça.fonte
Nenhuma das respostas anteriores é boa no Ubuntu. Tente o seguinte:
Eu encontrei isso aqui
fonte
Isso é adequado para mim em um Mac:
Ele excluirá
vendor
e dirá oapp/cache
nome da pesquisa com o sufixophp
.fonte
Para aqueles em versões mais antigas do UNIX que não podem usar -path ou -not
Testado no SunOS 5.10 bash 3.2 e no SunOS 5.11 bash 4.4
fonte
Como usar a opção de podar-de-encontrar-em-sh é uma excelente resposta de Laurence Gonsalves sobre como
-prune
funciona.E aqui está a solução genérica:
Para evitar digitar
/path/to/seach/
várias vezes, envolva ofind
em umpushd .. popd
par.fonte
-path
deve corresponder ao nome que a impressão seria impressa se fosse para imprimir o diretório, por exemplo, por exemplofind . -path ./.git -prune -o -print
, oufind $HOME/foo -path $HOME/foo/.git -prune -o -print
Algumas das respostas dizem apenas-path somedir
que infelizmente é não é exato o suficiente para ser útil.Para o que eu precisava, funcionou assim, encontrando
landscape.jpg
em todos os servidores a partir do root e excluindo a pesquisa no/var
diretório:find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d
lista todos os d diretórios em/
grep -v /var
exclui `/ var 'da listaxargs -I '{}' find '{}' -name landscape.jpg
execute qualquer comando, comofind
em cada diretório / resultado da listafonte
/
ainda não está excluído. Você pode precisarsed 1d
.Os seguintes comandos funcionam:
Se você tiver um problema com a localização, use a
-D tree
opção para visualizar as informações da análise de expressão.Ou o
-D all
, para ver todas as informações de execução.fonte
Encontrei o nome das funções nos arquivos de origem C excluindo * .o e exclua * .swp e exclude (arquivo não regular) e exclua a saída dir com este comando:
fonte
Melhor usar a
exec
ação que ofor
loop:O
exec ... '{}' ... '{}' \;
será executado uma vez para cada arquivo correspondente, substituindo os chavetas'{}'
pelo nome do arquivo atual.Observe que os colchetes estão entre aspas simples para protegê-los da interpretação como pontuação do script do shell * .
Notas
* Na seção EXEMPLOS da
find (GNU findutils) 4.4.2
página de manualfonte
exec
ação com frequência e acho muito útil. Eu normalmente adiciono aspas entre o{}
caso de haver espaços nos caminhos do arquivo que são fornecidos"{}"
.{}
funciona para arquivos com espaços em branco em seus nomes) e uma olhada nas páginas do manual, parece que a citação é necessária apenas para evitar que eles sejam mal interpretados como pontuação do script de shell. Nesse caso, você usaria aspas simples:'{}'
cp
oumv
ourm
. Eu vou dar uma olhadaEu tentei o comando acima, mas nenhum dos que usam "-prune" funciona para mim. Eventualmente, eu tentei isso com o comando abaixo:
fonte