Ho riscontrato lo stesso problema su Mac OSX , utilizzando un ZSH shell:in questo caso non c'è -t
opzione per mv
, quindi ho dovuto trovare un'altra soluzione. Tuttavia il seguente comando ha avuto successo:
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
Il segreto era citare le parentesi graffe . Non c'è bisogno che le parentesi graffe siano alla fine del exec
comando.
Ho provato con Ubuntu 14.04 (con BASH e ZSH shell), funziona allo stesso modo.
Tuttavia, quando si utilizza il +
segno, sembra infatti che debba trovarsi alla fine del exec
comando.
La pagina di manuale (o il manuale GNU online) spiega praticamente tutto.
trova il comando -exec {} \;
Per ogni risultato, command {}
viene eseguito. Tutte le occorrenze di {}
sono sostituiti dal nome del file. ;
è preceduto da una barra per impedire alla shell di interpretarlo.
trova il comando -exec {} +
Ogni risultato viene aggiunto a command
ed eseguito successivamente. Tenendo conto dei limiti di lunghezza del comando, immagino che questo comando possa essere eseguito più volte, con la pagina di manuale che mi supporta:
il numero totale di invocazioni del comando sarà molto inferiore al numero di file corrispondenti.
Nota questa citazione dalla pagina di manuale:
La riga di comando è costruita più o meno nello stesso modo in cui xargs costruisce le sue righe di comando
Ecco perché non sono consentiti caratteri tra {}
e +
ad eccezione degli spazi bianchi. +
fa in modo che find rilevi che gli argomenti dovrebbero essere aggiunti al comando proprio come xargs
.
La soluzione
Fortunatamente, l'implementazione GNU di mv
può accettare la directory di destinazione come argomento, con -t
o il parametro più lungo --target
. Il suo utilizzo sarà:
mv -t target file1 file2 ...
Il tuo find
comando diventa:
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
Dalla pagina di manuale:
comando -exec;
Esegui comando; true se viene restituito lo stato 0. Tutti i seguenti argomenti da trovare sono considerati argomenti del comando fino a quando non viene visualizzato un argomento costituito da `;' si incontra. La stringa `{}' è sostituita dal nome del file corrente che viene elaborato ovunque ricorra negli argomenti del comando, non solo negli argomenti in cui è da solo, come in alcune versioni di find. Potrebbe essere necessario eseguire l'escape di entrambe queste costruzioni (con un `\') o citarle per proteggerle dall'espansione da parte della shell. Vedere la sezione ESEMPI per esempi sull'uso dell'opzione -exec. Il comando specificato viene eseguito una volta per ogni file corrispondente. Il comando viene eseguito nella directory iniziale. Ci sono inevitabili problemi di sicurezza che circondano l'uso dell'azione -exec; dovresti usare invece l'opzione -execdir.
-exec comando {} +
Questa variante dell'azione -exec esegue il comando specificato sui file selezionati, ma la riga di comando viene creata aggiungendo alla fine ogni nome di file selezionato; il numero totale di invocazioni del comando sarà molto inferiore al numero di file corrispondenti. La riga di comando è costruita più o meno allo stesso modo in cui xargs costruisce le sue righe di comando. All'interno del comando è consentita solo un'istanza di `{}'. Il comando viene eseguito nella directory iniziale.
L'equivalente standard di find -iname ... -exec mv -t dest {} +
per find
implementazioni che non supportano -iname
o mv
implementazioni che non supportano -t
è usare una shell per riordinare gli argomenti:
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "[email protected]" /dest/dir/' sh {} +
Usando -name '*.[cC][pP][pP]'
, evitiamo anche di fare affidamento sulle impostazioni locali correnti per decidere qual è la versione maiuscola di c
o p
.
Nota che +
, contrariamente a ;
non è speciale in nessuna shell quindi non ha bisogno di essere quotato (anche se citare non danneggerà, eccetto ovviamente con shell come rc
che non supportano \
come operatore di quotazione).
Il /
finale in /dest/dir/
è così che mv
fallisce con un errore invece di rinominare foo.cpp
a /dest/dir
nel caso in cui solo un cpp
il file è stato trovato e /dest/dir
non esisteva o non era una directory (o collegamento simbolico alla directory).