it-swarm.it

Batch rinominare i file nella riga di comando e Xargs

Quindi, ho la seguente struttura:

.
..
a.png
b.png 
c.png

Ho eseguito un comando per ridimensionarli

ls | xargs -I xx convert xx -resize xx.jpg

Ora la mia dir sembra così

.
..
a.png.jpg
a.png
b.png.jpg
b.png
c.png.jpg
c.png

La prima domanda è, come faccio a rinominare il file in modo che possa avere solo un'estensione. Non due. (in pratica, come faccio a ripulire il mio errore originale)?

La seconda domanda è, in futuro, usando xargs, come posso modificare l'estensione del file simular al secondo comando?

22
Cripto

come faccio a rinominare il file in modo che possa avere solo un'estensione.

cd dir/with/messedup/files

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

in futuro, usando xargs, come posso cambiare l'estensione del file simular al secondo comando?

Per quanto ne so, non si può fare. Il modo migliore per farlo sarebbe utilizzare un ciclo for con la sostituzione dei parametri simile a quella sopra:

for file in *.png; do
  convert "$file" -resize "${file%.png}.jpg"
done

Se hai file in sottodirectory che vuoi convertire, puoi reindirizzare find a un ciclo while read:

find . -type f -name '*.png' |
while read file; do
  convert "$file" -resize "${file%.png}.jpg"
done

NOTE:Generalmente viene considerata una cattiva idea per usare l'output di ls in uno script di Shell. Anche se il tuo esempio avrebbe funzionato bene, ci sono molti esempi in cui non funziona. Ad esempio, se i tuoi nomi di file hanno una nuova riga (che unix consente), ls probabilmente non sfuggirà a quelli per te. (Questo in realtà dipende dall'implementazione, che è un'altra ragione per non usare ls negli script, il cui comportamento varia notevolmente da una casella all'altra.) Otterrai risultati più coerenti se usi find in un ciclo while-read o file globbing (ad esempio *.png) in un ciclo for.

19
Tim Pote

Questo può essere fatto anche con xargs e sed per cambiare l'estensione del file.

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv

È possibile stampare il nome file originale insieme a ciò che si desidera sia il nome file. Quindi gli xarg usano questi due argomenti nel comando move. Per il one-liner, ho anche aggiunto un grep per filtrare tutto non un file * .png.

49
Schleis

Arriva tardi alla festa, ma ecco come puoi rinominare i file con xargs. Supponiamo di avere un sacco di file denominati fileN.svg.png e di chiamarli fileN.png dove N potrebbe essere una serie di numeri interi:

ls *.svg.png | xargs basename -s .svg.png | xargs -I {} mv {}.svg.png {}.png

I primi xargs usano basename per rimuovere entrambi .svg e .png per ottenere un filenameN giusto. Il secondo xargs riceve quel nome spoglio e usa la sostituzione per rinominare il file.

10
Dethe

Per eliminare il tuo errore, prova l'utility rename. Controlla la pagina di manuale per i dettagli.

Nel tuo caso, dovresti fare rename '.png.jpg' '.jpg' ./* se la tua directory corrente è impostata in modo appropriato.

Dato che hai convert disponibile, sto assumendo che tu abbia anche mogrify (imagemagick suite). Ogni volta che voglio farlo, copio i file in una directory diversa e uso invece mogrify. Di solito ho bisogno di questo solo per ridimensionare, ma se cambi anche il formato dell'immagine, mogrify gestirà i nomi dei file (crea nuovi file con i nomi file corretti).

Lo useresti come mogrify -format jpg -resize [size] ./*.png. Non sono sicuro di cosa debba fare -resize senza argomenti di geometria. Non è documentato e non funziona sulla mia macchina.

Come argomentato da Tim Pote, non penso che tu possa fare in modo che gli xarg gestiscano i nomi dei file e le estensioni separatamente.

6
Matej

Sono in ritardo per questa festa da circa 3 anni, ho appena avuto un problema simile che ho capito da solo. Ho avuto una lista di file PNG che ho convertito usando inkscape, perché il supporto svg di ImageMagick è scarso. 

Inizialmente li ho convertiti facendo:

find . -name "*.svg" -exec inkscape {} --export-png={}.png

Che ovviamente ha portato allo stesso problema, come pubblicato sopra.

file1.svg
file1.svg.png
file2.svg
file2.svg.png
file3.svg
file3.svg.png
file4.svg
file4.svg.png

Ho voluto rinominare * .svg.png in * .png, questo è quello con cui sono finito ...

find . -name "*.svg.png" -print0 | sed 's/.svg.png//g' | xargs -0 -I namePrefix mv namePrefix.svg.png namePrefix.png

Questo fa tre cose:

  1. trova in questa directory i file * .svg.png, -print0 stampa sullo standard output
  2. sed modifica lo standard output, in pratica swap .svg.png con niente, quindi mi piacerebbe ottenere: file1/file2/file3/file4
  3. xargs -0 per ottenere i dati da sed, -I fa riferimento al nome del file senza l'estensione, quindi mv nome file originale al nuovo nome file. Il Word namePrefix non è niente di speciale, volevo solo chiarirlo.

MODIFICARE

Mi rendo conto ora che questo è il modo più complesso per farlo. Si può semplicemente usare il comando rinomina.

rename 's/svg\.png/.png/' *
3
Paul J

La mia soluzione è simile a molte delle soluzioni xarg e particolarmente simile a Schleis '.

La differenza qui è una manipolazione completa delle espressioni regolari con i riferimenti delle corrispondenze e comandi sed che ignorano correttamente i file che non corrispondono, quindi non è necessario prefiltrare il proprio elenco.

Questo è anche sicuro per i file con spazi e shell meta.

Cambia \2 nella sostituzione con qualsiasi estensione desiderata.

ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
xargs -n 2 mv

Spiegazione

Il -n arg dice di non stampare nulla per impostazione predefinita, il comando T dice saltare alla fine dello script se il precedente comando s non ha fatto una sostituzione, il comando p stampa lo spazio del pattern (colpito solo se il comando s corrisponde ).

Il & nella sostituzione è un riferimento al contenuto della corrispondenza del nome file originale.

Se sostituiamo mv nel comando con bash -c 'echo "run($#) [email protected]"' bash allora possiamo vedere il numero di volte in cui mv verrebbe chiamato, e con il conteggio e il valore dei parametri:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
  xargs -n 2 bash -c 'echo "run($#) [email protected]"' bash
run(2) Rick.and.Morty.S03E02.720p.HDTV.x264-BATV.mkv Rick and Morty S03E02.mkv
run(2) Rick.and.Morty.S03E03.720p.HDTV.x264-BATV.mkv Rick and Morty S03E03.mkv
run(2) Rick.and.Morty.S03E04.720p.HDTV.x264-BATV.mkv Rick and Morty S03E04.mkv
run(2) Rick.and.Morty.S03E05.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E05.mkv
run(2) Rick.and.Morty.S03E06.720p.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E06.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E07.720p.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E07.mkv
run(2) Rick.and.Morty.S03E08.720p.HDTV.x264-BATV.mkv Rick and Morty S03E08.mkv
run(2) Rick.and.Morty.S03E09.720p.HDTV.x264-BATV.mkv Rick and Morty S03E09.mkv
run(2) Rick.and.Morty.S03E10.720p.HDTV.x264-BATV.mkv Rick and Morty S03E10.mkv
1
joshperry

Il mio tentativo da: https://www.tecmint.com/linux-image-conversion-tools/

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.png}.jpg"'

Utilizzo parallelo

parallel convert '{}' '{.}.jpg' ::: *.png
0
SergioAraujo