Localizar caminho de exclusão contendo arquivos específicos

2

Eu estou tentando encontrar todos os diretórios em uma pasta recursivamente enquanto excluo todos os submódulos git, excluindo todo o caminho que contém o arquivo .git . Como eu pude fazer isso?

Explicação:

O arquivo

.git existe na raiz de cada pasta de submódulos. Esta pasta do submódulo pode ser incluída em qualquer lugar.

Caso de teste

$ mkdir Test
$ cd Test
$ mkdir a
$ mkdir b
$ mkdir c
$ cd a
$ mkdir .git
$ cd ..
$ cd b
$ touch .git
$ cd ..
$ cd c
$ mkdir c1
$ mkdir c2
$ cd..
$ find . -type d \( \( ! -name . -exec [ -e {}/.git ] \; -prune \) -o \( \( \
 -name .git\
 -o -name .vscode\
 -o -name node_modules\
 -o -name Image\
 -o -name Rendered\
 -o -name iNotebook\
 -o -name GeneratedTest\
 -o -name GeneratedOutput\
  \) -prune \) -o -print \) | sort 

Resultados esperados

.
./a
./c
./c/c1
./c/c2
    
por Nikhil 13.09.2018 / 10:01

4 respostas

5

find actions também são testes, então você pode adicionar testes usando -exec :

find . \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print

Isso aplica três conjuntos de ações:

  • -exec [ -f {}/.git ] \; -prune remove diretórios contendo um arquivo chamado .git
  • -name .git -prune remove os diretórios com o nome .git (para que o comando não pesquise no diretório principal .git de um repositório)
  • -print imprime qualquer coisa que não tenha sido capturada pelo acima.

Para corresponder apenas aos diretórios, adicione -type d , antes de -print ou (para economizar tempo processando arquivos):

find . -type d \( \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print \)

Isso também funciona quando ele é executado em um diretório diferente de . , alterando o caminho find start:

find /some/other/path -type d \( \( -exec [ -f {}/.git ] \; -prune \) -o \( -name .git -prune \) -o -print \)
    
por 13.09.2018 / 11:08
3

Podemos criar um find recursivo:

Adicione as seguintes linhas a um arquivo de script:

#!/bin/bash
if [ ! -f "$1"/.git ]; then
    echo "$1"
    find "$1" -mindepth 1 -type d -prune -exec "$0" {} \;
fi

Eu nomeei o arquivo findifnotgit , mas isso não importa. Em seguida, torne-o executável

chmod u+x findifnotgit

Em seguida, execute-o com o caminho que você deseja executar como argumento:

./findifnotgit .

- > . para o diretório atual

ou

./findifnotgit /path/to/search/

Explicação :

  • if [ ! -f "$1"/.git ]; then ... fi Executa apenas o seguinte quando não houver .git dentro da pasta atual ( $1 )
  • Precisamos da opção -mindepth 1 para deixar não encontrar a pasta com a qual começamos, o que criaria um loop indefinido.
  • Precisamos de -prune para que o find não desça aos diretórios. Nós mesmos faremos isso dentro de -exec .
  • -exec "$0" {} chamará o mesmo script $0 com as descobertas.
por 13.09.2018 / 10:31
0

Aqui está como dizer ao find para não olhar dentro dos repositórios .git ou .hg.

find .  \( -iname '.git' -o -iname '.hg' \) -prune -false  -o -iname  '*thing-i-am-looking for*'
    
por 13.09.2018 / 10:51
0

Bit de um script sujo, mas isso encontrará todos os diretórios que não contêm um arquivo .git :

#!/bin/bash

# find dirs that contain *.git files and store in array
exclude_dirs=($(find . -type f -iname ".git" | xargs -i dirname {}))

# set up the base command
command="find . -type d"

# loop over each element in array by index
for i in $(seq 0 $(expr ${#exclude_dirs[@]} - 1)); do
    command="${command} -not -path ${exclude_dirs[$i]}"
done

# run the find
eval ${command}

editar:

corrigiu erros de sintaxe e atualizou *.git para .git

edit2:

sim, isso estava errado, minhas desculpas. Editado para que realmente funcione agora.

    
por 13.09.2018 / 10:33