Trova file che non si trovano in .gitignore


12

Ho trovato il comando che visualizza i file nel mio progetto:

find . -type f -not -path './node_modules*' -a -not -path '*.git*' \
       -a -not -path './coverage*' -a -not -path './bower_components*' \
       -a -not -name '*~'

Come posso filtrare i file in modo che non mostrino quelli che sono in .gitignore?

Ho pensato di usare:

while read file; do
    grep $file .gitignore > /dev/null && echo $file;
done

ma il file .gitignore può avere modelli glob (inoltre non funzionerà con percorsi se il file è in .gitignore), Come posso filtrare i file in base a modelli che possono avere globs?

Risposte:


11

gitprovvede git-check-ignorea verificare se un file è escluso da .gitignore.

Quindi puoi usare:

find . -type f -not -path './node_modules*' \
       -a -not -path '*.git*'               \
       -a -not -path './coverage*'          \
       -a -not -path './bower_components*'  \
       -a -not -name '*~'                   \
       -exec sh -c '
         for f do
           git check-ignore -q "$f" ||
           printf '%s\n' "$f"
         done
       ' find-sh {} +

Si noti che si pagherebbe un grande costo per questo perché il controllo è stato eseguito per ciascun file.


Cosa c'è find-sh {} +alla fine?
jcubic,


Ok, e cos'è find-sh?
jcubic,

@jcubic è il nome che hai dato per lo script inline-sh, quindi nel caso si verifichi un errore, avresti un messaggio di errore significativo
cuonglm

@jcubic Prova find /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +ad esempio
cuonglm

9

c'è un comando git per fare esattamente questo: es

my_git_repo % git grep --line-number TODO                                                                                         
desktop/includes/controllers/user_applications.sh:126:  # TODO try running this without sudo
desktop/includes/controllers/web_tools.sh:52:   TODO: detail the actual steps here:
desktop/includes/controllers/web_tools.sh:57:   TODO: check if, at this point, the menurc file exists. i.e. it  was created

Come hai detto, eseguirà un grep di base con la maggior parte delle normali opzioni grep, ma non cercherà .gitné alcun file o cartella nel tuo .gitignorefile.
Per maggiori dettagli, vediman git-grep

sottomoduli:

Se hai altri repository git all'interno di questo repository git (dovrebbero essere in sottomoduli), puoi usare il flag anche --recurse-submodulesper cercare nei sottomoduli


Fantastico, quasi funziona perché ho altri repository git nella directory corrente, ecco perché ho "* .git".
jcubic,

8

Per mostrare i file presenti nel tuo checkout e che sono tracciati da Git, usa

$ git ls-files

Questo comando ha una serie di opzioni per mostrare, ad esempio file memorizzati nella cache, file non tracciati, file modificati, file ignorati ecc git ls-files --help. Vedere .


Ci penso anche, git ls-filesma non credo che abbia l'opzione per mostrare i file non tracciati, quale?
cuonglm,

1
@cuonglm -o(altro). Ad esempio,git ls-files -o -X .gitignore
Kusalananda

Ah sì, ma non riesco a gestire il caso in cui il file è stato tracciato in precedenza ma includilo in .gitignore.
cuonglm,

Nota minore: questo non elenca i file effettivi dal sistema ma i file inclusi nella cronologia di git. Questa può essere una sottile differenza nei sistemi senza distinzione tra maiuscole e minuscole (ad es. Condivisioni Windows). Di ', ho commesso ./foo.txt ma poi lo ho rinominato in ./Foo.txt. Alcuni client git non riconosceranno questa modifica e git ls-filesgenereranno ./foo.txt mentre findprodurrebbero ./Foo.txt
Griddo,

2

È possibile utilizzare un array in cui verrà eseguito bash glob.

Avere file come questo:

touch file1 file2 file3 some more file here

E avere un ignorefile come questo

cat <<EOF >ignore
file*
here
EOF

utilizzando

arr=($(cat ignore));declare -p arr

Risulterà a questo:

declare -a arr='([0]="file" [1]="file1" [2]="file2" [3]="file3" [4]="here")'

È quindi possibile utilizzare qualsiasi tecnica per manipolare tali dati.

Personalmente preferisco qualcosa del genere:

awk 'NR==FNR{a[$1];next}(!($1 in a))'  <(printf '%s\n' "${arr[@]}") <(find . -type f -printf %f\\n)
#Output
some
more
ignore

gitignoreè un superset di bashglob, ti perderai qualcosa del genere!file*
cuonglm,

@cuonglm Cosa vuoi dire con !file*? Come modello glob nel file ignore o come nome file?
George Vasiliou,

gitignoreaccetta il modello di file come !file*escludere i file con inizio file, e anche doppia stella**
cuonglm

.gitignoreha un sacco di funzioni, che potrebbero non essere così facili da implementare direttamente in Bash: git-scm.com/docs/gitignore . Sebbene gli ignoranti costituiti da semplici globs dovrebbero essere fattibili in Bash, senza awk o simili
ilkkachu,

@cuonglm Intendi la traduzione di !as not? Forse il globaling esteso può gestire questa situazione. Informazioni su doublestar, bash può gestirlo con shopt -s globstar.
George Vasiliou,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.