Frage

Ich verstehe das von der angegebene Beispiel nicht ganz man find, Kann mir jemand ein paar Beispiele und Erklärungen geben? Kann ich einen regulären Ausdruck darin kombinieren?


Die detailliertere Frage ist wie folgt:

Schreiben Sie ein Shell -Skript, changeall, was eine Schnittstelle hat wie changeall [-r|-R] "string1" "string2". Es wird alle Dateien mit einem Suffix von finden .h, .C, .cc, oder .cpp und alle Ereignisse von verändern string1 zu string2. -r ist Option, nur in aktuellem Dir zu bleiben oder Subdirs einzubeziehen.

HINWEIS:

  1. Für nicht rekursive Fall, ls ist nicht erlaubt, wir konnten nur verwenden find und sed.
  2. Ich habe es versucht find -depth Aber es wurde nicht unterstützt. Deshalb habe ich mich gefragt, ob -prune könnte helfen, aber das Beispiel nicht verstanden von man find.

Edit2: Ich habe Auftrag gemacht, ich habe keine Frage in guten Details gestellt, weil ich sie selbst beenden möchte. Da ich es bereits getan habe und es eingreift, kann ich jetzt die ganze Frage angeben. Außerdem habe ich es geschafft, die Aufgabe zu beenden, ohne es zu verwenden -prune, aber würde es trotzdem lernen.

War es hilfreich?

Lösung

Das, worüber ich mich verwirrt habe -prune ist, dass es eine Aktion ist (wie -print), kein Test (wie -name). Es verändert die "To-Do" -Liste, aber immer wahr zurückgibt.

Das allgemeine Muster für die Verwendung -prune ist das:

find [path] [conditions to prune] -prune -o \
            [your usual conditions] [actions to perform]

Du willst so ziemlich immer das -o (logisch oder) unmittelbar danach -prune, weil dieser erste Teil des Tests (bis hin zu und einschließlich -prune) wird zurückkehren FALSCH Für das Zeug, das du tatsächlich willst (dh: das Zeug du dich nicht will ausgehen).

Hier ist ein Beispiel:

find . -name .snapshot -prune -o -name '*.foo' -print

Dies findet die "*.foo" -Dateien, die nicht unter ".snapshot" -Verzeichnungen sind. In diesem Beispiel, -name .snapshot macht das [conditions to prune], und -name '*.foo' -print ist [your usual conditions] und [actions to perform].

Wichtige Notizen:

  1. Wenn Sie nur die Ergebnisse ausdrucken möchten, werden Sie möglicherweise gewohnt, das auszulassen -print Aktion. Sie im Allgemeinen nicht will das tun, wenn du benutzst -prune.

    Das Standardverhalten von Find ist zu "und" die gesamte Ausdruck mit dem -print Aktion, wenn es keine anderen Handlungen gibt als -prune (Ironischerweise) am Ende. Das bedeutet, dass das schreibe:

    find . -name .snapshot -prune -o -name '*.foo'              # DON'T DO THIS
    

    entspricht dem Schreiben Folgendes:

    find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
    

    Das bedeutet, dass es auch den Namen des Verzeichnisses ausdrucken wird, das Sie beschneiden, was normalerweise nicht das ist, was Sie wollen. Stattdessen ist es besser, die explizit anzugeben -print Aktion, wenn Sie das wollen:

    find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. Wenn Ihre "übliche Bedingung" zu Dateien übereinstimmt, die auch zu Ihrer Pflaumenbedingung übereinstimmen nicht in die Ausgabe aufgenommen werden. Der Weg, dies zu beheben, besteht darin, a hinzuzufügen -type d Prädikat für Ihren Pflaumenzustand.

    Angenommen, wir wollten jedes Verzeichnis beschneiden, das mit dem begonnen hat .git (Dies ist zugegebenermaßen etwas erfunden - normalerweise müssen Sie nur das genannte Ding entfernen exakt .git), aber ansonsten wollte alle Dateien, einschließlich Dateien wie .gitignore. Sie könnten dies versuchen:

    find . -name '.git*' -prune -o -type f -print               # DON'T DO THIS
    

    Das würde nicht enthalten .gitignore im Ausgang. Hier ist die feste Version:

    find . -type d -name '.git*' -prune -o -type f -print       # DO THIS
    

Zusätzlicher Tipp: Wenn Sie die GNU -Version von verwenden find, die Texinfo -Seite für find hat eine detailliertere Erklärung als seine Manpage (wie für die meisten GNU -Dienstprogramme gilt).

Andere Tipps

Achten Sie darauf, dass -Prune nicht verhindert irgendein Verzeichnis, wie einige gesagt haben. Es verhindert, dass sich in Verzeichnisse, die dem Test entsprechen, auf den sie angewendet werden, einhergehen. Vielleicht helfen einige Beispiele (siehe unten für ein Regex -Beispiel). Entschuldigung dafür, dass dies so langwierig ist.

$ find . -printf "%y %p\n"    # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh

$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test

$ find . -prune
.

$ find . -name test -prune
./test
./dir1/test
./dir2/test

$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl

$ find . -name test -prune -regex ".*/my.*p.$"
(no results)

$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test

$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py

$ find . -not -regex ".*test.*"                   .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

Normalerweise machen wir die native Art und Weise, wie wir Dinge unter Linux machen und wie wir denken, von links nach rechts.
Sie würden also schreiben, was Sie zuerst suchen:

find / -name "*.php"

Dann drücken Sie wahrscheinlich die Eingabetaste und stellen fest, dass Sie zu viele Dateien aus Verzeichnissen erhalten, die Sie nicht möchten. Lassen Sie uns /Medien ausschließen, um zu vermeiden, dass Sie Ihre montierten Laufwerke durchsuchen.
Sie sollten jetzt nur den folgenden Befehl anhängen:

-print -o -path '/media' -prune

Der endgültige Befehl lautet also:

find / -name "*.php" -print -o -path '/media' -prune

............... | <--- Include ---> | .................... | <- -------- Ausschließen ----------> |

Ich denke, diese Struktur ist viel einfacher und korreliert mit dem richtigen Ansatz

Hinzu kommt zu den Ratschlägen in anderen Antworten (ich habe keinen Repräsentanten, um Antworten zu erstellen) ...

Beim Kombinieren -prune Bei anderen Ausdrücken gibt es einen subtilen Verhaltensunterschied, je nachdem, welche Ausdrücke verwendet werden.

@Laurence Gonsalves 'Beispiel findet die "*.foo" -Dateien, die nicht unter ".snapshot" -Verzeichnungen sind:-

find . -name .snapshot -prune -o -name '*.foo' -print

Dieser etwas andere Short-Hand wird jedoch möglicherweise versehentlich auch die auflisten .snapshot Verzeichnis (und alle verschachtelten .snapshot-Verzeichnisse):-

find . -name .snapshot -prune -o -name '*.foo'

Der Grund ist (gemäß der Manpage auf meinem System):-

Wenn der gegebene Ausdruck keine der Vorwahlen -exec, -ls, -ok oder -print enthält, wird der gegebene Ausdruck wirksam ersetzt durch:

(gegebene_expression) -print

Das zweite Beispiel entspricht dem Eintritt in Folgendes, wodurch die Gruppierung von Begriffen geändert wird:-

find . \( -name .snapshot -prune -o -name '*.foo' \) -print

Dies wurde zumindest auf Solaris 5.10 gesehen. Nachdem ich ungefähr 10 Jahre lang verschiedene Geschmacksrichtungen von *Nix verwendet habe, habe ich erst kürzlich aus einem Grund gesucht, warum dies geschieht.

Prune ist ein Recurse bei keinem Verzeichnisschalter.

Von der Mannseite

Wenn -Tepth nicht gegeben ist, wahr; Wenn die Datei ein Verzeichnis ist, steigen Sie nicht hinein. Wenn -Tepth gegeben ist, falsch; Kein Effekt.

Grundsätzlich wird es nicht in Sub -Verzeichnisse eingehen.

Nehmen Sie dieses Beispiel:

Sie haben die folgenden Verzeichnisse

  • /home/test2
  • /home/test2/test2

Wenn du läufst find -name test2:

Es wird beide Verzeichnisse zurückgeben

Wenn du läufst find -name test2 -prune:

Es kehrt nur/home/test2 zurück, da es nicht in/home/test2 abfällt, um/home/test2/test2 zu finden

Ich bin kein Experte darin (und diese Seite war sehr hilfreich zusammen mit http://mywiki.wooledge.org/usingfind)

Gerade bemerkt -path ist für einen Weg, den Übereinstimmung mit der String/Pfad, die kurz danach kommt find (. in diesen Beispielen) wo as -name entspricht allen Grundnamen.

find . -path ./.git  -prune -o -name file  -print

Blockiert das .git -Verzeichnis in Ihrem aktuellen Verzeichnis ( Wie Ihre Feststellung in . )

find . -name .git  -prune -o -name file  -print

Blockiert alle .git -Unterverzeichnisse rekursiv.

Beachten Sie das ./ ist extrem wichtig !! -path muss einen Pfad entsprechen, der verankert ist . oder was auch immer kommt, kurz nach dem Finden Wenn Sie übereinstimmen, ohne dass es aus der anderen Seite des oder 'ist-o') Da wird es wahrscheinlich nicht beschnitten! Ich war mir dessen naiv nicht bewusst und es brachte mich dazu, -Path zu verwenden, wenn es großartig ist, wenn Sie nicht das gesamte Unterverzeichnis mit dem gleichen Grundnamen beschneiden möchten: D.

Zeigen Sie alles, einschließlich Dir selbst, aber nicht seinen langweiligen Inhalt:

find . -print -name dir -prune

Wenn Sie hier alle guten Antworten lesen, ist mein Verständnis jetzt, dass die folgenden die gleichen Ergebnisse zurückgeben:

find . -path ./dir1\*  -prune -o -print

find . -path ./dir1  -prune -o -print

find . -path ./dir1\*  -o -print
#look no prune at all!

Aber Der letzte wird viel länger dauern, da es immer noch alles in dir1 durchsucht. Ich denke, die eigentliche Frage ist, wie es geht -or unerwünschte Ergebnisse aus, ohne sie tatsächlich zu durchsuchen.

Ich denke, Prune bedeutet also keine anständigen Vergangenheit, sondern markieren Sie es wie getan ...

http://www.gnu.org/software/findutils/manual/html_mono/find.html"Dies ist jedoch nicht auf die Auswirkung der '-prunen'-Aktion zurückzuführen (die nur weitere Abstammung verhindert, stellt nicht sicher, dass wir diesen Element ignorieren). Stattdessen ist dieser Effekt auf die Verwendung von' -o 'zurückzuführen. Da die linke Seite des „oder“ Zustands für ./src/emacs gelungen ist, ist es für diese bestimmte Datei überhaupt nicht erforderlich, die rechte Seite ('-Druck') zu bewerten.

find Erstellt eine Liste von Dateien. Es wendet das Prädikat an, das Sie jedem zur Verfügung gestellt haben, und gibt diejenigen zurück, die passieren.

Diese Idee das -prune bedeutet für mich wirklich verwirrend. Sie können eine Datei ohne Pflaumen ausschließen:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

Alle -prune Verändert das Verhalten der Suche. Wenn das aktuelle Spiel ein Verzeichnis ist, heißt es "Hey find, diese Datei, die Sie gerade abgestimmt haben, steigen Sie nicht hinein. ". Es wird nur diesen Baum (aber nicht die Datei selbst) aus der Liste der Dateien zu suchen.

Es sollte benannt werden -dont-descend.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top