GNU/Linux >> Linux Esercitazione >  >> Linux

Perché find -exec mv {} ./target/ + non funziona?

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).


Linux
  1. In che modo Linux gestisce più separatori di percorsi consecutivi (/home////nomeutente///file)?

  2. Linux:differenza tra /dev/console , /dev/tty e /dev/tty0?

  3. Bash =~ Regex e HTTPS://regex101.com/?

  4. Perché /bin/sh punta a /bin/dash e non a /bin/bash??

  5. Come scoprire da quale cartella è in esecuzione un processo?

Linux – /sbin/init non esiste?

/sys/ documentazione?

echo o print /dev/stdin /dev/stdout /dev/stderr

Perché le directory /home, /usr, /var, ecc. hanno tutte lo stesso numero di inode (2)?

Perché sono necessari < o > per usare /dev/tcp

I siti web dovrebbero vivere in /var/ o /usr/ in base all'utilizzo consigliato?