Wie verwende ich `find -exec`, um den Befehl im Verzeichnis der gefundenen Datei (nicht im aktuellen Verzeichnis) auszuführen?

14

Lassen Sie uns sagen , dass ich in einem Verzeichnis bin , die einige Unterverzeichnisse hat, dir1, dir2, und dir3. Jedes dieser Verzeichnisse hat eine Datei, foound ich möchte für jedes fooVerzeichnis in jedem der Verzeichnisse denselben Befehl ausführen und diesen Befehl in diesem Verzeichnis ausführen lassen .

Wenn ich es "von Hand" machen würde, würde es ungefähr so ​​aussehen:

cd dir1
(execute on foo)
cd ../dir2
(execute on foo)
cd ../dir3
(execute on foo)

Der Befehl muss unbedingt in jedem der Verzeichnisse ausgeführt werden . fooist ein Stapelplanungsskript (für HTCondor, wenn Sie es wissen möchten) und muss von jedem Unterverzeichnis ausgeführt werden, damit die Ausgabe der von den Planungsskripten gestarteten Läufe in jedem Unterverzeichnis landet.

Die Frage " Eine Datei suchen und einen Befehl im Verzeichnis der Datei ausführen " beantwortet meine Frage nicht, soweit ich das beurteilen kann. Die erste Antwort auf diese Frage ist eher eine Problemumgehung, die in meinem Fall nicht funktioniert, und die zweite Antwort enthält nicht genügend Erklärungen, damit ich weiß, wie man sie verwendet.

NeutronStar
quelle
@roaima, bitte erklären Sie, wie es ein Duplikat ist. Die erste Antwort dieser Frage ist nicht helfen Sie mir, es ist mehr eine Arbeit um, und die zweite Antwort macht keinen Sinn für mich. Ich brauche mehr Erklärungen, um zu wissen, wie man es benutzt.
NeutronStar

Antworten:

22

Angenommen, Sie findunterstützen dies, verwenden Sie die -execdirOption anstelle von-exec

find * -name 'foo' -execdir pwd \;

Wenn dies nicht der Fall ist, geben Sie bitte Details zu Ihrer Plattform und / oder Distribution an (falls zutreffend).

Roaima
quelle
Wenn Sie auf "Suchen: Der relative Pfad './node_modules/.bin' klicken, ist in der Umgebungsvariablen PATH enthalten": askubuntu.com/questions/621132/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Tut mir leid, wenn ich es so schreiben darf, aber -execdir (unter Ubuntu) ist Scheiße, weil es dir nicht gibt {}, sondern dem Elternteil von {}.
uav
1
@uav ohne Ihren Anwendungsfall zu kennen, kann ich Ihnen nicht helfen. Als Antwort auf Ihren Fehler wird in der Dokumentation jedoch eindeutig " Gefällt-exec mir , aber der angegebene Befehl wird aus dem Unterverzeichnis ausgeführt, das die übereinstimmende Datei enthält " angegeben.
Roaima
Ja, richtig, es ist ein Sonderfall, wenn Sie nach -type d (= Verzeichnis) suchen und es dann nicht optimal ist.
uav
Ohne Ihren Anwendungsfall zu kennen, kann ich Ihnen nicht helfen.
Roaima
3

Angenommen, Sie wissen genau, in welchen Verzeichnissen Sie Ihren Befehl ausführen sollen.

for dir in dir1 dir2 dir3; do
    ( cd "$dir" && somecommand foo )
done

oder Schleifen über die fooDateien,

for foo in */foo; do
  ( cd "${foo%/*}" && somecommand foo )
done

Die Subshell verhindert cd, dass das Arbeitsverzeichnis des restlichen Skripts beeinflusst wird. Die ${foo%/*}Parametersubstitution wird auf den Namen des Verzeichnisses erweitert, in dem sich die fooDatei befindet (indem alles nach dem letzten /im Wert von entfernt wird $foo).

Verwenden Sie Standard find, um dasselbe zu tun (für den Fall, dass sich die fooDateien möglicherweise tief in einer Verzeichnisstruktur befinden):

find . -type f -name foo -exec sh -c '
    for foo do
        ( cd "${foo%/*}" && somecommand foo )
    done' sh {} +

In Worten: Suchen Sie alle regulären Dateien mit dem Namen "foo" irgendwo im aktuellen Verzeichnis oder darunter und geben Sie diesem Shell-Skript ihre Pfadnamen in Stapeln. Das Shell-Skript muss die angegebenen Pfadnamen durchlaufen, das Verzeichnis in den Verzeichnisabschnitt jedes Pfadnamens ändern und in diesem Fall ausführen somecommand foo.

Eine Lösung, die den Nichtstandard verwendet -execdir, finden Sie in der Antwort von roaima . Seine Antwort passte sich meinem Beispiel an:

find . -type f -name foo -execdir somecommand foo ';'
Kusalananda
quelle