Suchen Sie nach Dateien, die sich nicht in .gitignore befinden


11

Ich habe einen Befehl find, der Dateien in meinem Projekt anzeigt:

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

Wie kann ich die Dateien filtern, damit nicht die Dateien in .gitignore angezeigt werden?

Ich dachte, dass ich benutze:

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

Aber .gitignore-Dateien können Glob-Muster haben (auch funktioniert es nicht mit Pfaden, wenn sich die Datei in .gitignore befindet). Wie kann ich Dateien basierend auf Mustern filtern, die möglicherweise Globs haben?

Antworten:


11

gitbietet git-check-ignorean, um zu überprüfen, ob eine Datei von ausgeschlossen ist .gitignore.

Sie könnten also verwenden:

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 {} +

Beachten Sie, dass Sie hierfür hohe Kosten zahlen würden, da die Prüfung für jede Datei durchgeführt wurde.


Was ist find-sh {} +am Ende?
jcubic


Ok, und was ist find-sh?
Jcubic

@jcubic ist der Name, den Sie für Inline-Sh-Skript gegeben haben, so dass im Falle eines Fehlers eine aussagekräftige Fehlermeldung
angezeigt wird

@jcubic Versuchen Sie find /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +zum Beispiel
cuonglm

9

Es gibt einen Git-Befehl, um genau dies zu tun: z

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

Wie Sie angegeben haben, werden die meisten normalen Grep-Optionen mit einem einfachen Grep ausgeführt, es werden jedoch .gitkeine Dateien oder Ordner in Ihrer .gitignoreDatei durchsucht .
Weitere Einzelheiten finden Sie unterman git-grep

Submodule:

Wenn Sie andere Git-Repos in diesem Git-Repo haben (diese sollten sich in Submodulen befinden), können Sie das Flag auch --recurse-submoduleszum Suchen in den Submodulen verwenden


Großartig, es funktioniert fast, weil ich andere Git-Repos im aktuellen Verzeichnis habe, deshalb habe ich "* .git".
Jcubic

8

Verwenden Sie, um Dateien anzuzeigen, die sich in Ihrer Kasse befinden und von Git verfolgt werden

$ git ls-files

Dieser Befehl bietet eine Reihe von Optionen zum Anzeigen, z. B. zwischengespeicherte Dateien, nicht verfolgte Dateien, geänderte Dateien, ignorierte Dateien usw. Siehe git ls-files --help.


Ich denke auch darüber nach git ls-files, glaube aber nicht, dass es die Möglichkeit gibt, nicht verfolgte Dateien anzuzeigen. Welche?
Cuonglm

1
@ Cuonglm -o(andere). ZBgit ls-files -o -X .gitignore
Kusalananda

Ah ja, aber ich kann den Fall nicht behandeln, in dem die Datei zuvor verfolgt wurde, sondern in .gitignore.
Cuonglm

Kleiner Hinweis: Hier werden nicht die tatsächlichen Dateien aus dem System aufgelistet, sondern die Dateien, die im Git-Verlauf enthalten sind. Dies kann bei Systemen ohne Berücksichtigung der Groß- und Kleinschreibung (z. B. Windows-Freigaben) ein geringfügiger Unterschied sein. Angenommen, ich habe ./foo.txt festgeschrieben, es dann aber in ./Foo.txt umbenannt. Einige Git-Clients erkennen diese Änderung nicht und geben git ls-files./foo.txt aus, während findsie ./Foo.txt ausgeben
Griddo

2

Sie können ein Array verwenden, in dem Bash Glob ausgeführt wird.

Dateien wie diese haben:

touch file1 file2 file3 some more file here

Und eine ignoreDatei wie diese zu haben

cat <<EOF >ignore
file*
here
EOF

Verwenden von

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

Wird dazu führen:

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

Sie können diese Daten dann mit einer beliebigen Technik bearbeiten.

Ich persönlich bevorzuge so etwas:

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

gitignoreist eine Obermenge von bashGlob, die Sie für so etwas wie!file*
cuonglm

@cuonglm Was meinst du damit !file*? Als Glob-Muster in Ignorierdatei oder als Dateiname?
George Vasiliou

gitignoreAkzeptieren Sie !file*file**
Dateimuster

.gitignoreEs gibt eine Reihe von Funktionen, die möglicherweise nicht so einfach direkt in Bash zu implementieren sind: git-scm.com/docs/gitignore . Obwohl Ignorieren, die nur aus einfachen Globs bestehen, in einfachem Bash ohne awk oder so machbar sein sollten
ilkkachu

@cuonglm Du meinst Übersetzung von !als nicht? Möglicherweise kann Extended Globing mit dieser Situation umgehen. Über Doublestar kann Bash damit umgehen shopt -s globstar.
George Vasiliou
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.