Come usare `find -exec` per eseguire il comando nella directory del file trovato (non nella directory corrente)?


15

Diciamo che io sono in una directory che ha alcuni sottodirectory, dir1, dir2, e dir3. Ognuna di queste directory ha un file fooe vorrei eseguire lo stesso comando su ciascuna foodi ciascuna directory e far eseguire quel comando dall'interno di quella directory.

Se dovessi farlo "a mano", sarebbe simile a questo:

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

È indispensabile che il comando sia eseguito da ciascuna delle directory . fooè uno script di pianificazione batch (per HTCondor, se ti interessa sapere) e deve essere eseguito da ciascuna sottodirectory in modo che l'output delle esecuzioni avviato dagli script di pianificazione finisca in ogni sottodirectory.

La domanda " Trova un file ed esegui un comando nella directory del file ", per quanto ne so, non risponde alla mia domanda. La prima risposta a questa domanda è più una soluzione alternativa che non funzionerà nel mio caso, e la seconda risposta non ha abbastanza spiegazione per farmi sapere come usarla.


@roaima, per favore, spiega come è un duplicato. La prima risposta a questa domanda non mi aiuta, è più una soluzione, e la seconda risposta non ha alcun senso per me. Ha bisogno di maggiori spiegazioni per sapere come usarlo.
NeutronStar

Risposte:


23

Supponendo che findlo supporti, utilizzare l' -execdiropzione invece di-exec

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

In caso contrario, fornire i dettagli della propria piattaforma e / o distribuzione (a seconda dei casi).


Quando inizi a premere "trova: il percorso relativo './node_modules/.bin' è incluso nella variabile d'ambiente PATH,": askubuntu.com/questions/621132/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Scusa se posso scriverlo in quel modo, ma -execdir (su Ubuntu) è una merda, perché non ti dà {}, ma il genitore di {}.
1919

1
@uav senza conoscere il tuo caso d'uso non posso aiutarti. Ma in risposta al tuo whinge la documentazione indica chiaramente " Like -exec, ma il comando specificato viene eseguito dalla sottodirectory contenente il file corrispondente ".
roaima,

Sì, giusto, è un caso speciale se stai cercando -type d (= directory) e quindi non è ottimale.
UAV

Senza conoscere il tuo caso d'uso non posso aiutarti.
roaima,

4

Supponendo che tu sappia esattamente in quali directory eseguire il tuo comando,

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

oppure, passando in rassegna i foofile,

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

La subshell impedisce cddi influenzare la directory di lavoro del resto dello script. La ${foo%/*}sostituzione dei parametri si espande nel nome della directory in cui foorisiede il file (rimuovendo tutto dopo l'ultimo /valore di $foo).

Utilizzando standard findper fare la stessa cosa (nel caso in cui i foofile possano vivere in profondità in una struttura di directory):

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

In parole: trova tutti i file regolari chiamati "pippo" in qualsiasi punto della directory corrente o sotto e dai i loro nomi a questo script shell in batch. Lo script della shell deve scorrere i nomi dei percorsi indicati, cambiare la directory nella parte della directory di ciascun percorso e, se ciò ha esito positivo, eseguire somecommand foo.

Per una soluzione che utilizza non standard -execdir, vedere la risposta di roaima . La sua risposta si è adattata al mio esempio:

find . -type f -name foo -execdir somecommand foo ';'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.