Come rinominare i file e sostituire i caratteri?


11

Ho un gruppo di file che hanno :(due punti) all'interno del nome. Devo sostituire il :con -(trattino).

C'è un modo semplice per farlo in uno script?

Nome file di esempio: 2013-10-11:11:52:08_055456663_045585_.txt

Risposte:


17

Un semplice 1-liner dovrebbe fare (presuppone che shshell compatibile con Posix ):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Spiegazione:

  • for ... in ...; do ...; doneè un ciclo

  • *:* corrisponde a tutti i file e directory nella directory corrente che hanno il :loro nome

  • f viene assegnato a sua volta a ciascuno di tali nomi di file nel loop

  • mvrinomina il suo primo argomento nel secondo; -v(verboso) gli chiede di stampare ciò che fa; questa opzione è specifica per GNU-utils , quindi è disponibile su Linux ma non su Solaris

  • $(...) esegue il codice in una sotto-shell e sostituisce l'output

  • echo stampa il suo argomento sull'output standard

  • tr legge l'output standard e traduce i caratteri in base alla mappa fornita

Se stai usando bash , puoi evitare di generare una shell extra ( $()) con sottoprocessi ( tr) sostituendola $(...)con ${f//:/-}.


+1 per una semplice risposta funzionante, anche se potrebbe fare con qualche spiegazione in più. Ad esempio, il for f inciclo ... è un ciclo che scorre su tutti i file nella directory corrente in cui i file devono corrispondere *:*. (Cosa succede con le directory che corrispondono?). Il comando move è una novità oldname newname in cui il nuovo nome viene generato eseguendo una shell con $( subshell here ). Cosa fa tr ...
Hennes,

@Hennes: questo è un superutente - devo davvero approfondire questo tipo di dettagli? Oh bene,
eccoti

No. Se ci fosse una reale necessità, non avrei + +. E capisco cosa fa. Penso che sia bello per molti altri lettori però.
Hennes,

2
È possibile sostituire $(echo "$f" | tr ':' '-')con "${f//:/-}"ed evitare la chiamata di subshell, pipe e programma esterno. Penso che questo sia un bashismo, ma eh. Vedi qui .
evilsoup,

@evilsoup Indeed; non fa molta differenza per piccoli set di dati (e uno potrebbe favorire la leggibilità) ma rimarrai sorpreso dalla velocità con cui si somma qualcosa del genere. Ci sono stato un po 'di recente; riscrivere uno script in modo tale che due semplici comandi di massaggiamento delle stringhe non fossero più necessari per tagliare facilmente il tempo di esecuzione del 90% o più, che su un set di dati di grandi dimensioni tradotto in diversi minuti di esecuzione del wallclock.
un CVn

6

Come affermato in un altro post da me, lo renamestrumento potrebbe fare il trucco per te. Devi solo digitare rename s/:/-/ <files to rename> Questo sostituisce ogni due punti con un trattino in tutti i file che chiami alla fine, ad es2013-10-*

Ecco il link al mio altro post


1

Sono sicuro che un professionista UNIX potrebbe farlo con bash, ma ecco la mia versione veloce e sporca con ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

impostare path_to_files sul percorso dei file con nome errato. salva il codice sopra in un file chiamato rename.rb quindi:

username@machinename$ ruby rename.rb

@sds fornisce una risposta molto migliore. Devo cancellare la mia risposta? Sono nuovo di StackOverflow.
shupru,

1
No; ha ancora un valore significativo. :)
Blacklight Shining

2
Ci sono alcuni aspetti negativi importanti con questa risposta, tuttavia, che potrebbero essere rilevanti e che vale sicuramente la pena conoscere. (Potrebbe essere ancora utile, ma avvertimento emptor e tutto il resto.) In primo luogo, sembra che si rompa male quando incontra nomi di file con spazi bianchi (non solo la classica riga di errore in caso di non ritorno) in essi. Inoltre, anche se non fosse per uno spazio bianco, dovresti citare il nome del file nell'invocazione della shell per proteggere eventuali altri caratteri speciali nei nomi dei file dal trattamento da parte della shell (anche se non so esattamente come funzioni l'operatore backtick di Ruby ).
un CVn

1

Se hai solo uno o pochi file, questo può fare la ridenominazione per te:

  1. Conservare il modello del nome del file che state designando come variabile: p="201*".
  2. Memorizzare il vecchio nome del file che si desidera rinominare: old_name=$(ls | grep $p).
  3. Memorizza il nuovo nome file con i necessari sostituzioni di caratteri:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Pulizia bonus :
  a. Se per motivi di uniformità si desidera sostituire i trattini (-) insieme ai due punti (:) con caratteri di sottolineatura (_), è possibile farlo:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. Se vuoi che anche l'ultimo carattere di sottolineatura (poco prima del .txt) sia andato, imposta la new_namevariabile come:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Ora rinomina il tuo file come necessario: mv $old_name $new_name

         NB: mvfallirà se uno dei nomi dei file nell'operazione di ridenominazione contiene spaces. In tal caso, racchiudi le variabili appropriate tra virgolette, come:
mv "$old_name" $new_name OR mv $old_name "$new_name" OR mv "$old_name" "$new_name"


One-liner

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name

0

usando renamer :

$ renamer --find ":" --replace "-" *

Penso che installare un ambiente node.js completo solo per rinominare i file sia un po 'troppo. renameè uno strumento preinstallato su molte distribuzioni di Linux. Ma penso che per Windows questo strumento possa essere eccezionale.
noggerl,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.