La domanda in sé non è esatta, perché l'OP parla di:
- nomi di file come
ABC 123456
(senza estensione), ma nel codice di esempio usando *.txt
estensione
-
aggiungi un trattino tra due blocchi (ad esempio dov'è lo spazio) come
ABC - 123456
, ma nel prossimo prendi circa counting to 4
e count 3
, ad es. non è del tutto chiaro cosa dovrebbe fare lo script, ad esempio se trovi ABCD 12
o AB 345
- inoltre, vuoi mantenere lo spazio finale, ciò che è strano - ma OK;)
Il problema è divisibile in 3 parti separate:
- selezionando i file giusti per la rinomina
- preparare il nuovo nome file, sostituire / aggiungere caratteri al vecchio
- il "fisico" rinomina
Annuncio "selezione dei file giusti". La selezione dei file può essere eseguita da alcune utilità esterne, ad esempio dal comando find
.
I principali vantaggi di find
sono:
- può cercare i file in modo ricorsivo anche nelle sottodirectory
- è possibile selezionare con maggiore precisione i file giusti, ad es. escludere le directory, selezionare i file in base al tempo o alle dimensioni e così via. (controlla dal terminale
man find
.)
Annuncio "prepara il nuovo nome". Questo può essere fatto da programmi esterni,
come sed
o awk
o qualsiasi programma cosa può manipolare il testo nella shell
script, o può essere fatto (in alcuni casi semplici come questo) con
bash
stesso - ed è possibile salvare una costosa esecuzione di comandi.
(per hundert di migliaia di file fa la differenza).
Il seguente:
${file/ /-}
sostituisce (sostituisce) uno spazio (la parte / /
) con il trattino ( /-
). Quindi è possibile scrivere
mv "$file" "${file/ /-}"
e salva l'esecuzione di sed
.
Quindi una delle soluzioni alternative potrebbe essere , ad esempio:
#!/bin/bash
while IFS= read -r -d $'find . -maxdepth 1 -type f -iname "*.jpg" -print0 |\
perl -0nle '$n=$_; $n=~s/ /-/; rename $_,$n unless($_ eq $n || -e $n)'
' filename
do
newfilename="${filename/ /-}"
[[ "$filename" != "$newfilename" ]] && echo mv -i "$filename" "$newfilename"
done < <(find . -maxdepth 1 -type f -iname "* *.jpg" -print0)
L'abobe è per DRY RUN - mostrerà solo, cosa verrà fatto, per l'esecuzione reale rimuovi echo
.
di decomposizione:
-
seleziona i file giusti per la rinomina: il find . -maxdepth 1 -type f -iname "* *.jpg" -print0
troverà tutti
- cosa sono solo nella directory corrente (
-maxdepth 1
)
- e sono file semplici (
-type f
)
- e il loro nome corrisponde a (qualsiasi cosa) (spazio) (qualsiasi cosa) .jpg senza insensibilità - ad es. il nome deve contenere uno spazio
- fornisce i nomi di file come null terminato , quindi il loro nome può contenere anche il carattere di nuova riga. (
-print0
)
-
il ciclo while IFS= read -r -d $'find
' filename; do ... done < <( )
- legge l'output dal comando
-d $'-r
'
sopra
- dove i nomi dei file sono null terminati (
IFS=
)
- ignora tutti i caratteri di escape (
newfilename="${filename/ /-}"
) / argomento avanzato - non necessario per spiegare qui /
- il
bash
impedisce il taglio degli spazi bianchi iniziali e finali dal nome file (anche un argomento un po 'avanzato)
-
preparare il nuovo nome file ${filename/ /- }
- è fatto da
mv
internamente (senza eseguire un comando esterno).
- se vuoi preservare lo spazio finale dopo il trattino usa
man mv
-
l'attuale ridenominazione viene eseguita dal comando -i
(vedi mv
dal terminale), dove
- il
newfilename
che chiederà all'utente se qui c'è già un file con il nuovo nome file (non sovrascriverlo)
-
e filename
viene eseguito solo quando [[ "$filename" != "$newfilename" ]]
è diverso da mv
mv
La soluzione di cui sopra è per lo più soggetta a errori, ma non è ancora molto efficace,
perché per centinaia di migliaia di file verranno eseguite centinaia di
mille volte il comando find
.
La soluzione può essere: usando alcuni
utilità, che cosa può leggere i nomi dei file e fare la ridenominazione senza
eseguendo il comando mv
N-volte.
Ad esempio, la "pistola grande" del sistema ammette il "perl", come:
find . -maxdepth 1 -type f -iname "*.jpg" -print0 |\
perl -0nle '$n=$_; $n=~s/ /-/; print qq{old:$_ new:$n\n} unless($_ eq $n || -e $n)' #print instead of the rename
ciò che rinominerà tutti i file ciò che produce bash
in una esecuzione - ad es. molto più veloce di migliaia di% esecuzioni di%code%.
Il test Tor (DRY RUN) usa quanto segue:
${file/ /-}
Ps: il perl è abbastanza potente da gestire tutto da solo, ad es. anche il comando find, ma è un argomento più avanzato ...
Ps2: il mio inglese è molto peggio del mio %code% , quindi qualcuno potrebbe gentilmente modificare questo post per aggiungere / correggere le cose ..;)