trova con -execdir


15

Quando corro findcon -execdirnon ottengo i risultati che mi aspettavo.

Per esempio:

mkdir -p a/b/c
find . -type d -execdir touch foo \;
$ tree a
a
├── b
   ├── c
   └── foo
└── foo

La directory cnon contiene un foofile. Come posso findvisitare e fare qualcosa localmente in ogni directory?

Risposte:


18

Per ogni file corrispondente (ovvero ogni directory), findpassa alla directory che lo contiene (ovvero la directory principale) ed esegue il comando specificato. Poiché il comando non utilizza il nome della corrispondenza, non agirà mai su tutte le directory. Per questo particolare albero di directory, lo stai facendo

(cd . && touch foo)        # because ./a matches
(cd ./a && touch foo)      # because ./a/b matches
(cd ./a/b && touch foo)    # because ./a/b/c matches

Per creare un file in ogni directory, puoi semplicemente usare -execinvece di -execdir, a condizione che la tua implementazione di findpermette {}all'interno di un argomento (la maggior parte lo fa, e in particolare penso tutti quelli):

find . -type d -exec touch {}/foo +

Per la portabilità POSIX, è necessario eseguire manualmente l'assemblaggio del nome della directory e del nome della base file.

find . -type d -exec sh -c 'touch "$0/foo"' {} \;

o (leggermente più veloce)

find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +

In alternativa, è possibile utilizzare la corrispondenza jolly ricorsiva di bash. Fai attenzione che (a differenza della funzione corrispondente in ksh e zsh, e diversamente dal tuo findcomando) bash reclute sotto collegamenti simbolici alle directory.

shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done

Una soluzione zsh:

touch ./**/(e\''REPLY+=foo'\')

FYI: man bashstati in "-c": gli argomenti dopo command_string sono assegnati a parametri posizionali che iniziano con $ 0, tuttavia "per d" ripeterà i parametri posizionali che iniziano con $ 1. "_" è un testo assegnato a $ 0 e non verrà utilizzato.
Chad Skeeters,

3

Il comando viene eseguito in ogni directory che contiene un file corrispondente. Poiché cnon contiene una directory, non corrisponde e quindi non verrà eseguito lì.

La soluzione è aggiungere il nome della directory all'argomento execdir, in questo modo:

find . -type d -execdir touch {}/foo \;

2

A partire dal man file

   -execdir command {} +
          Like  -exec,  but  the  specified  command is run from the subdirectory containing the matched file

La tua directory di corrispondenza crisiede nella bdirectory in modo che sia eseguito da exec. Funzionerebbe come previsto se stai cercando file invece di directory.

Probabilmente potresti ottenere ciò che desideri inviando le directory in xargsquanto verrà fornito l'elenco completo delle directory.

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.