2012-11-05 11 views
5

Ho un codice funzionante, è molto semplice - copia ogni file * .jpg, lo rinomina in * 1.jpg, nessuna preoccupazione.Bash, esegui script su ogni file .jpg in una directory con sottodirectory

for i in *.jpg; do cp $i ${i%%.jpg}1.jpg; done 

come posso eseguire questo, in modo che funzioni su tutti i file in una directory, tutti i file nelle sottodirectory di quella directory

struttura di directory di esempio:

test/test1/test2/somefile.jpg 
    test/anotherfile.jpg 
    test/test1/file.jpg 
etc 
+2

'ogni file nelle sottodirectory di quella directory' = in modo ricorsivo – nickhar

risposta

6

Il comando per fare qualsiasi cosa in modo ricorsivo a una struttura di directory è find:

find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' \; 

L'utilizzo di -exec anziché for i in $(find ...) gestirà i nomi di file che contengono uno spazio. Certamente, c'è ancora una frase che vince; se il nome file contiene ", lo file="{}" si espanderà a file="name containing "quote characters"", che è ovviamente rotto (file diventerà name containing quote e proverà ad eseguire il comando characters).

Se si dispone di tali nomi di file, o si potrebbe, quindi stampare ogni nome di file separato con caratteri nulli (non consentiti nei nomi dei file) utilizzando -print0, e utilizzare while read -d $'\0' i loop negli nulli delimitati risultati:

find . -name "*.jpg" -print0 | \ 
    (while read -d $'\0' i; do cp "$i" "${i%%.jpg}1.jpg"; done) 

Come con qualsiasi comando complesso come questo, è una buona idea testarlo senza eseguire alcunché per assicurarsi che si stia espandendo a qualcosa di sensato prima di eseguirlo. Il modo migliore per farlo è quello di anteporre il comando vero e proprio con echo, così invece di eseguirlo, vedrete i comandi che verrà eseguito:

find . -name "*.jpg" -print0 | \ 
    (while read -d $'\0' i; do echo cp "$i" "${i%%.jpg}1.jpg"; done) 

Una volta che hai eyeballed ei risultati sembra buono, rimuovere echo ed eseguirlo di nuovo per eseguirlo per davvero.

+0

trovare. -name "* .jpg" -exec bash -c 'file = "{}"; cp "$ file" "$ {file %%. jpg} 1.jpg" '\; è lo script corretto, grazie mille – user1051532

2

Se si dispone di Bash 4, è possibile utilizzare globstar per consentire l'espansione dei nomi ricorsiva (cioè le partite file nelle sottodirectory così)

shopt -s globstar 
for i in **/*.jpg; do cp "$i" "${i%%.jpg}1.jpg"; done 

p/s: ho aggiunto virgolette gli argomenti per cp nel caso ci sono spazi nei nomi di file o quant'altro.

Problemi correlati