
Ich versuche, GNU dazu zu bringen, Ausschlusseinträge BIS zum angegebenen Dateinamen zu finden.
Nehmen Sie diesen Beispielbaum:
./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt
(In den und anderen Verzeichnissen gäbe es world
noch eine Menge anderer Dateien, deshalb suche ich nicht einfach nach hello.txt
).
Ich möchte alles außer „test.txt“ und den übergeordneten Verzeichnissen abgleichen.
Die Ausgabe sollte einfach sein foo/bar/world/hello.txt
.
Dieser Befehl erzeugt die richtigen Ergebnisse, ist jedoch ziemlich chaotisch und würde falsche Ergebnisse erzeugen, wenn es mehrere Verzeichnisse mit den gleichen Namen gäbe:
find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world
Antwort1
Geben Sie an , dass find
Sie nur an Dateien und nicht an Verzeichnissen interessiert sind.
find ./foo -type f ! -name test.txt
Aktualisieren:
Nehmen wir dieses etwas komplexere Beispiel an:
$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
Wenn Ihr Ziel das Löschen von Dingen ist, müssen Sie angeben, -depth
dass Dateien vor ihren Verzeichnissen angezeigt werden:
$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
Wenn Sie den Pfad kennen, den Sie behalten möchten, können wir einen regulären Ausdruck entwickeln, der mit Teilen davon übereinstimmt:
$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
Dann können wir den regulären Ausdruck einfach negieren, um das zu erhalten, was Sie entfernen möchten:
$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
Antwort2
Wenn Sie die genaue Tiefe des Baums kennen (d. h. Sie möchten die Dateien ab dem dritten Ordner abrufen), können Sie Folgendes verwenden:
find . -mindepth $depth ! -name test.txt
Mit Ihrer Verzeichnisstruktur erhalte ich:
$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt
Und das ist genau das, was Sie erwarten.
EDIT: das sollte besser sein (aber hässlicher!). Es findet das Verzeichnis, in dem test.txt
sich befindet, und findet alle darin enthaltenen Dateien. Der Vorteil ist, dass es völlig unabhängig von den übergeordneten Pfaden ist, da es diese automatisch berechnet.
EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"
Mehrzeilig ist besser:
EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"