Eu quero listar todos os arquivos, exceto aqueles dentro .git/
do diretório find
apenas com o comando.
Eu tentei isso:
$ find . -path .git -prune -type f
$
ele retornou 0 arquivos (em vez dos 2 que eu tenho), então eu tentei isso:
$ find . -not -path .git -type f | grep -c '\.git'
1770
$
Eu não entendo porque nada disso está funcionando, você pode ajudar?
EDIT0 : Graças a @icarus, vejo que os caminhos devem ser precedidos ./
e que estava faltando o OR
operador consequentemente, este comando funciona:
$ find . -path ./.git -prune -o -type f | grep '\.git'
./.git
./.gitignore
$
EDIT1: Por que esse outro comando não funciona?
$ find . -not -path ./.git -a -type f | grep -c '\.git'
1770
$
EDIT2: Uma última pergunta: por que o -prune
predicado precisa de um -o -print
para não imprimir o ./.git
e ./.gitignore
resulta no comando abaixo:
$ find . -name ".git*" -prune | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -o -print | grep -c git
0
EDIT3: Obrigado @rastafile:
$ find . -name ".git*" -prune | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -print | grep git
./.git
./.gitignore
$ find . -name ".git*" -prune -o -print | grep git
$
Parece que o GNU encontra -prune
chamadas de predicado -print
implicitamente quando a expressão anterior é verdadeira:
Se a expressão não contiver outras ações além de -prune, -print será executado em todos os arquivos para os quais a expressão for verdadeira.
Em conclusão: O comando que eu preciso é:
$ find . -name ".git*" -prune -o -type f -print
Obrigado a todos.
A operação padrão para juntar termos em find é
and
tãosignifica encontrar arquivos que pertencem ao root e são chamados de fred. Você quer fazer uma
or
operação, se ela for chamada de ".git" então podá-la ou se for um arquivo então listá-lo.Observe que estou usando
-name
em vez de-path
. Se você fornecer um local inicial de.
, o.git
diretório no nível superior será chamado./.git
para fins de-path
.Então
não dá nada porque nada corresponde
-path .git
à medida que todos os arquivos são iniciados./
fornece todos os arquivos porque tudo corresponde
-not -path .git
, portanto, a única filtragem é-type f
restringir a saída aos arquivos.Há uma grande diferença entre
-path
e-name
-- eles não são nada parecidos: "name" só olha para a última parte, "path" para toda a cadeia de barras. O que um "nome de arquivo" deve significar, ou um "nome de caminho", é sempre um pouco controverso. Mas aqui é claro e importante.Isso funciona (você diz):
Você começa com
.
, então o gitdir padrão é encontrado e removido. Nenhum outro./.git
existe, então todos os outros (-o
) são verificados quanto ao tipo de arquivo.Seu último exemplo:
não funciona, apenas encontra todos os arquivos .
Se você deseja evitar
-prune
, deve corresponder a cada entrada dentro:Concordo com a combinação -name/-prune de Icarus, mas tenho uma modificação:
Os parênteses não são necessários, aqui.
Mesmo que
-name '*git*'
seja adicionado, para testar/reduzir a saída.A ação explícita
-print
no final suprime uma impressão por poda:Eu não tinha certeza sobre os pais; Eu procurei
man find
(GNU) e encontrei este bom detalhe sobre eles:Para mim, a clareza seria reforçada por:
Mas assim não funciona!
E se você deixar o
-a
like aqui, o-o
destaque se destaca o suficiente, então os parênteses podem ser deixados de fora, também para maior clareza.(Como o shell também gosta de parênteses, você precisa citá-los . Mas adeus à clareza.)
O sem aspas
!
pode funcionar (o meu funciona), o sem aspas*
não.Então, para encontrar arquivos (todos os tipos), exceto em qualquer diretório
.git
:(o tipo -d também pode ser deixado de fora, se você não se importar ... veja o comentário de Kamil ... é uma selva lá fora , e find é uma pequena linguagem de programação : o que você precisa)