Führen Sie einen Befehl aus, in dem eine Datei gefunden wird

7

Wie führe ich einen Befehl aus, bei dem eine Datei gefunden wird?
Angenommen, ich habe ein Verzeichnis mit dem Namen testdir:

$ ls -R testdir/
testdir/:
dir1  dir2  dir3  dir4  dir5

testdir/dir1:
doc1.pdf

testdir/dir2:
file1.txt

testdir/dir3:
doc2.pdf

testdir/dir4:
file2.txt

testdir/dir5:
doc5.pdf

Jetzt möchte ich eine Aktion ausführen (einen Befehl ausführen), bei der findeine bestimmte Datei / ein bestimmter Dateityp gefunden wird. Lassen Sie mich zum Beispiel finden *.pdf:

$ find . -name '*.pdf'
./testdir/dir3/doc2.pdf
./testdir/dir5/doc5.pdf
./testdir/dir1/doc1.pdf

Angenommen, ich möchte einen Befehl ausführen (z. B. touch file), in dem der obige Befehl Dateien findet. Mit anderen Worten, ich möchte eine Datei mit dem Namen filein jedem Verzeichnis erstellen, in dem mindestens eine .pdfgefunden wurde, damit ich Folgendes erhalte:

$ ls -R testdir/
testdir/:
dir1  dir2  dir3  dir4  dir5

testdir/dir1:
doc1.pdf  file

testdir/dir2:
file1.txt

testdir/dir3:
doc2.pdf  file

testdir/dir4:
file2.txt

testdir/dir5:
doc5.pdf  file

Wie mache ich eine solche Arbeit?
Kann für jede gefundene Datei sein, cdwo Datei vorhanden ist und einen Befehl rekursiv ausführen.
Ich weiß, dass das findeine großartige Funktion hat: -execaber ich kann es nicht zum Laufen bringen.


Dies ist nur ein Beispiel, um eine Vorstellung davon zu bekommen, was ich tun möchte. Allgemein: Wie führe ich einen Befehl aus, bei dem Dateien findrekursiv gefunden werden?

Pandya
quelle
Willkommen zur Tag-Korrektur, falls vorhanden.
Pandya
3
Ihr Fund hat möglicherweise die Option -execdirdazu.
Meuh

Antworten:

11

Wenn Sie diesen Befehl touch fileausführen, wird Ihr Befehl möglicherweise mehrmals in dem Verzeichnis ausgeführt, in dem der Befehl gestartet wurde:

find -name '*.pdf' -exec touch file \;

Wenn Sie diese Variante ausführen, wird jede Instanz des Befehls im Verzeichnis der Zieldatei ausgeführt:

find -name '*.pdf' -execdir touch file \;

In beiden Fällen können Sie dies in Aktion sehen, indem Sie das touch filedurch entweder echo {}und / oder ersetzen pwd.


Von der Manpage:

-execdir command ;
-execdir command {} +

    Wie -exec, aber der angegebene Befehl wird aus dem Unterverzeichnis ausgeführt, das die übereinstimmende Datei enthält. Dies ist normalerweise nicht das Verzeichnis, in dem Sie gestartet haben find.

Roaima
quelle
2

Sie können das Verzeichnis des Dateinamens mit extrahieren dirnameund von dort übernehmen.

find . -name "*.pdf" -type f -exec bash myscript {} \;

wobei die Datei myscriptFolgendes enthält:

dir=$(dirname "$1")
cd "$dir"
touch file
klimpergeist
quelle
es funktioniert nicht, hast du es versucht? Es wird filenur in einem Ordner erstellt, den es zuerst findet
Edward Torvalds
Ich weiß, warum es nicht funktioniert, jetzt bearbeiten Sie Ihre Antwort :)
Edward Torvalds
2

Mit können zshSie Glob-Qualifizierer verwenden, um z. B. nur .pdfDateien auszuwählen , und über Modifikatoren die Verzeichnisnamen in einem Array mit eindeutigen Elementen und dann cdin jedem dieser Verzeichnisse speichern und Ihren Befehl ausführen. Auf diese Weise führen Sie Ihren Befehl nur einmal in jedem Verzeichnis aus, unabhängig von der Anzahl der .pdfin diesem Verzeichnis gefundenen s:

dirlist=(**/*.pdf(.:a:h))
for d in ${(u)dirlist[@]}
  (cd $d && touch file)

oder

typeset -U dirlist
dirlist=(**/*.pdf(.:a:h))
for d in ${dirlist}
  (cd $d && touch file)

Sie können Modifikatoren und Qualifizierer weiter kombinieren, z. B. um nach regulären Dateien (versteckt und nicht versteckt) mit der Erweiterung zu suchen .bkpund eindeutige Verzeichnisnamen in einem Array zu speichern:

dirlist=(**/*.bkp(D.:a:h))
don_crissti
quelle
0

Suchen Sie nicht weiter als entr:

https://bitbucket.org/eradman/entr

Sie können entr ein bestimmtes Verzeichnis überwachen lassen. Wenn find die Datei findet, berühren Sie eine Datei mit dem Namen triggerfile.txt in diesem Verzeichnis und lassen Sie entr übernehmen.

Hüpfender Hase
quelle