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?

jcubic
quelle

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.

cuonglm
quelle
Was ist find-sh {} +am Ende?
jcubic
@jcubic siehe unix.stackexchange.com/q/12902/38906
cuonglm
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

the_velour_fog
quelle
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.

Kusalananda
quelle
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
George Vasiliou
quelle
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