Wie kann ich versteckte Dateien und Verzeichnisse bei einer Suche mit eingebetteten Platzhaltern ausschließen / ignorieren?

119

Ab ( Platzhalter vor und nach "etwas Text" beachten )

find . -type f -name '*some text*'

Wie kann man alle versteckten Dateien und Verzeichnisse ausschließen / ignorieren?

Ich habe schon viel zu lange gegoogelt, bin auf einiges gestoßen und! (Ausrufezeichen) Parameter, aber kein passendes (und sparsames) Beispiel, das gerade funktioniert hat .

Piping | zu grepwäre eine Option und ich würde auch Beispiele dafür begrüßen; aber in erster Linie interessiert mich einen kurzen Einzeiler (oder ein paar Stand-alone - Einzeiler, veranschaulicht verschiedene Möglichkeiten, den gleichen Befehlszeilen Ziel zu erreichen) nur mit find.

ps: Dateien in Linux suchen und bestimmte Verzeichnisse ausschließen scheint eng miteinander verbunden zu sein, aber a) wird noch nicht akzeptiert und b) ist verwandt, aber anders und verschieden, aber c) kann Inspiration liefern und helfen, die Verwirrung zu lokalisieren!

Bearbeiten

find . \( ! -regex '.*/\..*' \) -type f -name "whatever"funktioniert. Der reguläre Ausdruck sucht nach "irgendetwas, dann nach einem Schrägstrich, dann nach einem Punkt und dann nach irgendetwas" (dh nach allen versteckten Dateien und Ordnern einschließlich ihrer Unterordner) und dem "!" negiert den regulären Ausdruck.

verrückt nach natty
quelle
Hilft nicht, was Sie in Ihrer Bearbeitung gefragt haben, aber werfen Sie einen Blick auf meine Frage und deren Antwort hier: unix.stackexchange.com/q/69164/15760 und auch den Link in der Antwort.

Antworten:

134

Dies druckt alle Dateien, die Nachkommen Ihres Verzeichnisses sind, und überspringt versteckte Dateien und Verzeichnisse:

find . -not -path '*/\.*'

Wenn Sie also nach einer Datei mit some textdem Namen suchen und versteckte Dateien und Verzeichnisse überspringen möchten, führen Sie Folgendes aus:

find . -not -path '*/\.*' -type f -name '*some text*'

Erläuterung:

Mit dieser -pathOption wird ein Muster anhand der gesamten Pfadzeichenfolge überprüft. *ist ein Platzhalter, /ist ein Verzeichnis-Trennzeichen, \.ist ein Punkt (es muss maskiert werden, um eine besondere Bedeutung zu vermeiden) und *ist ein weiterer Platzhalter. -notbedeutet, dass Sie keine Dateien auswählen, die diesem Test entsprechen.

Ich denke nicht, dass finddas klug genug ist, um zu vermeiden, dass versteckte Verzeichnisse im vorherigen Befehl rekursiv durchsucht werden. Wenn Sie also Geschwindigkeit benötigen, verwenden Sie -prunestattdessen Folgendes:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print
Flimm
quelle
Beachte beim letzten, dass du das -printam Ende brauchst ! -name '\.*' would be more efficient instead of Ich bin mir auch nicht sicher, ob -path` (da der Pfad nach Unterpfaden sucht, diese jedoch entfernt werden)
artfulrobot
Was ist die besondere Bedeutung .in diesem Zusammenhang?
Frostschutz
@frostschutz Der Punkt nach findbedeutet das aktuelle Verzeichnis: Es findwerden alle Dateien und Verzeichnisse unter dem aktuellen Verzeichnis angezeigt . Das nachfolgende Argument pathist ein regulärer Ausdruck, bei dem ein Punkt normalerweise "ein beliebiges Zeichen" bedeutet. Damit es sich um einen wörtlichen Punkt handelt, müssen wir ihn mit einem Backslash maskieren. Das Argument nach -name ist kein regulärer Ausdruck, aber es erweitert Platzhalter wie ?und *wie eine Shell.
Flimm,
2
@frostschutz Eigentlich, wenn ich es mir überlege, kann ich mich irren, wenn es um .eine besondere Bedeutung geht.
Flimm
1
@ Flimm yup, keine Notwendigkeit zu entkommen .. Soweit mir bekannt ist , nur müssen diese maskiert werden: *, ?, und [].
Doan
10

Dies ist eine der wenigen Möglichkeiten, um Punktdateien auszuschließen, die auch unter BSD, Mac und Linux korrekt funktionieren:

find "$PWD" -name ".*" -prune -o -print
  • $PWD Den vollständigen Pfad zum aktuellen Verzeichnis ausgeben, damit der Pfad nicht mit beginnt ./
  • -name ".*" -prune Stimmt mit allen Dateien oder Verzeichnissen überein, die mit einem Punkt beginnen und dann nicht absteigen
  • -o -printbedeutet, den Dateinamen zu drucken, wenn der vorherige Ausdruck nicht mit irgendetwas übereinstimmt. Wenn Sie -printoder verwenden, werden -print0alle anderen Ausdrücke standardmäßig nicht gedruckt.
Eradman
quelle
Bitte erläutern Sie "alarmierend kompliziert"; Die bereits gegebenen Antworten und Ihre Antwort scheinen das Gegenteil zu beweisen ...?
verrückt nach natty
2
"alarmierend kompliziert" ist wahrscheinlich übertrieben. Ich habe die Antwort umformuliert, um auf den Punkt zu kommen. Ich denke, die Antwort, die ich gepostet habe, ist schwer zu verstehen und ohne sorgfältiges Lesen der Manpage schwer zu sehen. Wenn Sie nur GNU find verwenden, gibt es mehr mögliche Lösungen.
Eradman
-o ... -printist hilfreich. Für meine Verwendung habe ich jetzt find ... '!' -name . -name '.*' -prune -o ... -print, was bequemer war als mit $ PWD.
Roger Pate
4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Schließt alle versteckten Verzeichnisse und versteckten Dateien unter $ DIR aus

Gast
quelle
Das ist die perfekte Antwort. Es findet rekursiv alle Dateien, schließt jedoch Werbebuchungen für Verzeichnisse und versteckte Dateien aus. Vielen Dank!
KyleFarris
2

Die Antwort, die ich ursprünglich als "Bearbeitung" meiner ursprünglichen Frage oben gepostet habe:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever"funktioniert. Der reguläre Ausdruck sucht nach "irgendetwas, dann nach einem Schrägstrich, dann nach einem Punkt und dann nach irgendetwas" (dh nach allen versteckten Dateien und Ordnern einschließlich ihrer Unterordner) und dem "!" negiert den regulären Ausdruck.

verrückt nach natty
quelle
Ähnlich, aber nur für den aktuellen Ordner:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt
2

Sie müssen dafür nicht verwenden find. Verwenden Sie einfach globstar in der Shell selbst, wie:

echo **/*foo*

oder:

ls **/*foo*

wo **/für einen beliebigen Ordner rekursiv und *foo*jede Datei , die hat fooin seinem Namen.

Standardmäßig werden mit lsDateinamen ohne versteckte Dateien und Verzeichnisse gedruckt.

Wenn Sie das Globbing nicht aktiviert haben, tun Sie dies mit shopt -s globstar.

Hinweis: Eine neue Globbing-Option funktioniert in Bash 4, zsh und ähnlichen Shells.


Beispiel:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden
Kenorb
quelle
5
Das brauchst du nicht ls! echo **/*foo*
Kevin Cox
@kenorb (und @ kevin-cox). Könnten Sie etwas ausführlicher sein? Warum sollte globstar (= *) hier funktionieren und wie? Was macht der Schrägstrich?
Nussig über natty
@nuttyaboutnatty /bedeutet Ordner, es trennt Verzeichnisse vom Dateinamen. *im Grunde alles darstellt.
Kenorb
@kenorb ja-aber: wie hilft der einzeiler bei der ursprünglichen frage?
verrückt nach natty
1
@nuttyaboutnatty Beispiel wurde verdeutlicht und hinzugefügt. Es hilft, indem es Dateien findet, die die versteckten ignorieren.
Kenorb
1

@ Flimms Antwort ist gut, vor allem, weil es verhindert, dass Fundstücke in versteckte Verzeichnisse gelangen . Ich bevorzuge diese Vereinfachung:

Im Allgemeinen, um alle versteckten Pfade (normale Dateien, Verzeichnisse usw.) auszuschließen:

find <start-point> -path '*/.*' -prune -o <expression> -print

Verwenden Sie beispielsweise Ihr Arbeitsverzeichnis als Startpunkt und -name '*some text*'als Ausdruck:

find . -path '*/.*' -prune -o -name '*some text*' -print

Im Gegensatz zu der Antwort von @ Flimm sind keine versteckten Dateien oder Verzeichnisse der einfache Fall. Der -path '*/.*'Ausdruck gilt für alle Pfade (reguläre Dateien, Verzeichnisse usw.), die .unmittelbar nach dem Dateitrennzeichen stehen /. Diese Zeile schneidet also sowohl versteckte Dateien als auch Verzeichnisse.

Das Zulassen ausgeblendeter Dateien beim Ausschließen ausgeblendeter Verzeichnisse erfordert einen weiteren Filter. Hier würden Sie -type dden zu beschneidenden Ausdruck einfügen.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Zum Beispiel:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

In diesem Fall -type d -path '*/.*'gilt dies truenur für Verzeichnisse. Daher werden nur Verzeichnisse beschnitten.

De Novo
quelle
0

findhat nette logische Schalter wie -andund -notSie können sie zu Ihrem Vorteil nutzen, um eine passende Datei mit zwei Regeln zu finden:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Wie Sie sehen können, findverwendet zwei Regeln -name '*hidden_file*'und -and \( -not -name ".*" \)diese Dateinamen zu finden , die beiden Bedingungen entsprechen - Dateinamen mit hidden_filedrin , aber ohne Punkt führt. Beachten Sie die Schrägstriche vor Klammern - sie werden verwendet, um Klammern als findArgumente zu definieren, anstatt eine Unterschale zu definieren (was Klammern sonst ohne Schrägstriche bedeuten).

Sergiy Kolodyazhnyy
quelle
0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Anmerkungen:

  • . : aktueller Ordner
  • entfernen -maxdepth 1, um rekursiv zu suchen
  • -type f: finde Dateien, nicht Verzeichnisse ( d)
  • -not -path '*/\.*' : nicht zurückkehren .hidden_files
  • sed 's/^\.\///g': entferne das vorangestellte ./aus der Ergebnisliste
Victoria Stuart
quelle