Ich habe folgendes Problem:
Das Verzeichnis Example1
enthält drei Dateien: Example1
, Things
und Pictures
.
Das Verzeichnis Example2
enthält drei Dateien: Example2
, Example3
und Pictures
.
Ich brauche eine Liste, die nur die Dateien anzeigt, die mit dem Verzeichnisnamen übereinstimmen. Dies sind: Example1
und Example2
. Ich habe es mit diff, find, locate und ls versucht ... aber ich habe nichts erreicht.
Antwort1
Sie können Dateinamen, die denselben Namen wie das enthaltene Verzeichnis haben, problemlos mit einem Regex abgleichen, der eine Rückverweis verwendet. Dies sind Dateinamen der Form, what/ever/something/something
bei denen die beiden something
Teile identisch sind und keinen Schrägstrich enthalten. In der BRE-Regex-Syntax [^/]*
entspricht dies jeder Zeichenfolge, die keinen Schrägstrich enthält, \(/[^/]*\)
entspricht einem Schrägstrich, gefolgt von einer beliebigen Anzahl von Zeichen, die kein Schrägstrich sind, und macht das Ganze zu einer Gruppe, und \1
entspricht demselben Text, der von der ersten Gruppe abgeglichen wird, \(/[^/]*\)\1
entspricht also zwei Pfadsegmenten mit demselben Namen. Fügen Sie .*
am Anfang hinzu, um die vorherigen Verzeichniskomponenten abzugleichen.
Mit GNU find, FreeBSD find, macOS find oder allen anderen, find
die Folgendes unterstützen -regex
:
find . -regex '.*\(/[^/]*\)\1'
Antwort2
Da es im Allgemeinen weniger Verzeichnisse als Dateien gibt, suchen wir nach allen Verzeichnissen und testen anschließend, ob sie den erforderlichen Dateinamen enthalten.
find . -type d -exec sh -c '
for dirpath do
filepath="$dirpath/${dirpath##*/}"
[ -f "$filepath" ] && printf "%s\n" "$filepath"
done' sh {} +
Dadurch werden die Pfadnamen aller regulären Dateien (und symbolischen Links zu regulären Dateien) gedruckt, die sich in einem Verzeichnis mit demselben Namen wie die Datei befinden.
Der Test wird in einem kurzen Inline- sh -c
Skript durchgeführt, das eine Reihe von Verzeichnispfadnamen als Argumente erhält. Es durchläuft jeden Verzeichnispfadnamen und erstellt einen Dateipfadnamen mit dem gesuchten Namen. Das ${dirpath##*/}
im Code könnte durch ersetzt werden $(basename "$dirpath")
.
Für die angegebene Beispielverzeichnisstruktur würde dies ausgeben:
./Example1/Example1
./Example2/Example2
Um einfach zu testen,jeder Name, nicht nur normale Dateien, ändern Sie den -f
Test in einen -e
Test.
Antwort3
Verwenden find -exec
:
find . -type f \
-exec sh -c '[ "$(basename "$1")" = "$(basename "$(dirname "$1")")" ]' find-sh {} \; \
-print
Die -print
Ausführung erfolgt nur, wenn das Ergebnis darin [ ... ]
wahr -exec sh -c '...'
ist.
Ausgabe:
./Example1/Example1
./Example2/Example2