Rinomina di massa, versione * nix


11

Stavo cercando un modo per rinominare un numero enorme di file con nomi simili , molto simile a questo (una domanda relativa a Windows) tranne per il fatto che sto usando * nix (Ubuntu e FreeBSD, separatamente). Riassumendo, mentre uso la shell (Bash, CSH, ecc.) Come rinominare in massa un numero di file tale che, ad esempio, i seguenti file:

Beethoven - Fur Elise.mp3
Beethoven - Moonlight Sonata.mp3
Beethoven - Ode to Joy.mp3
Beethoven - Rage Over the Lost Penny.mp3

sarà rinominato come questi?

Fur Elise.mp3
Moonlight Sonata.mp3
Ode to Joy.mp3
Rage Over the Lost Penny.mp3

Il motivo per cui voglio fare questo è che questa raccolta di file andrà in una directory chiamata "Beethoven" (cioè il prefisso dei nomi dei file) e che queste informazioni sul nome del file stesso saranno ridondanti.

Risposte:


12

L'utilità di ridenominazione farà ciò che desideri.

Basta usare rename 's/Beethoven\ -\ //g' *.mp3


Puoi modificare per fornire un collegamento all'utilità o è standard in entrambe le distribuzioni menzionate (Ubuntu e FreeBSD)?
Chris W. Rea,

1
Viene fornito con Perl. Debian lo usa come comando di ridenominazione, quindi sospetto che anche Ubuntu lo faccia. C'è un altro comando 'rinomina' che è inutile, quindi controlla la pagina man.
derobert,

wow, la sintassi di rinomina sembra molto simile a Vim Sostituisci: D
Dzung Nguyen

il port in / usr / doors / sysutils / rename ha funzionato perfettamente in FreeBSD
Josh W.

10

Come tante altre cose con Linux / Unix, c'è più di un modo per farlo!

Alcuni potrebbero usare mmv (massa mv).

Anche il comando rename o prename fornito con alcuni pacchetti Perl (Ubuntu e Debian più recenti) può fare altrettanto.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Nota che lo strumento di rinomina su Fedora 10 non è lo stesso programma di questo e funziona in modo diverso. Fa parte di un pacchetto diverso, util-linux-ng e può essere trovato qui .

Vado spesso nella shell per fare un giro per abitudine (dopo che tutti questi strumenti non sono sempre esistiti).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Questo creerà la directory di Beethoven, quindi sposta il file in quella directory / nome file, in cui il nome file ha "Beethoven -" sostituito con nulla.

Come test, prima di:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

Dopo:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3

4

Prova questa soluzione, implementata usando una combinazione di grep e rinomina. Questo presuppone che tu abbia un sacco di directory che devi rinominare. Se ce ne sono solo alcuni, sceglierei l'approccio manuale, con il modello "Artista -" codificato per ciascuno di essi.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Spiegazione di find :
il comando find trova tutti i file con estensione .mp3 nella gerarchia di file corrente e chiama l'argomento passato a -exec per ciascuno. Si noti che all'interno di -exec , {} si riferisce all'argomento passato da find (percorso file + nome). Le \;garantisce la ;viene passato al rinomina e invece di indicare la fine del ritrovamento comando.

Il comando dato sopra ha l' opzione -n (nessuna azione); quindi ti dirà cosa succederebbe solo se lo avessi eseguito. Ti consiglio di eseguire questo comando senza l'opzione -n ​​solo dopo averlo eseguito una volta e sei soddisfatto dei risultati proposti.

Ora per la regexp.

  • ^ corrisponde all'inizio della stringa.
  • $ corrisponde alla fine della stringa.
  • . corrisponde a qualsiasi personaggio.
  • *significa zero o più del costrutto precedente. ad es. .*significa zero o più caratteri.
  • \s sta per qualsiasi personaggio spaziale.
  • \S sta per qualsiasi carattere non spaziale.
  • Nulla all'interno (), viene catturato e viene riflessa come $1, $2a seconda della sua posizione.

Il regexp:

  • Cerca una struttura di directory opzionale all'inizio, la cattura in $ 1: (.*/)
  • Salta tutto fino al " -":.*-
  • Cattura il resto della stringa, ad eccezione degli spazi iniziali e finali, in $ 2: (.*)
  • Riscrive il file come $ 1 $ 2, che dovrebbe essere "/path/to/file/""filename.mp3"

Ecco la mia corsa di prova:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

I regexp sono affari complicati, e ho fatto molti errori scrivendoli, quindi accetterei qualsiasi contributo sulla mancanza di merito di questo. So di aver trovato parecchi test questo.


1

Ho creato un programma Java da riga di comando che semplifica la ridenominazione di file (e directory), soprattutto per gli script. È gratuito e open source, quindi puoi modificarlo a tuo piacimento:

RenameWand
http://renamewand.sourceforge.net/

Alcuni esempi di utilizzo rilevanti:

Spostare i file del modulo "<a> - <b>"nella rispettiva directory "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Ordina i file in base all'ora dell'ultima modifica e rinominali con un numero di 3 cifre:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Riorganizza parti del nome file e cambia caso:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"

1

zmv Lo strumento di ridenominazione zsh è molto buono.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Altre note qui ...


0

Per le teste di Penguin questo è facilmente eseguibile in uno script shell o in uno script AWK. Per noi semplici mortali potresti voler provare Midnight Commander. È sulla maggior parte delle distribuzioni di Linux, da un prompt della shell digitare mc -a. Puoi rinominare i file usando le espressioni regolari. Ho usato l'articolo su GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ per aiutarmi.


0

Ecco un semplice esempio da riga di comando. Avevo la parola "bianco" nel mezzo dei nomi di un mucchio di file png. Volevo eliminarlo e lasciare un solo trattino basso. Questo ha fatto il trucco:

for i in *.png; do mv "$i" "${i/white/}"; done

0

Utilizzare vidir e quindi utilizzare le funzionalità dell'editor per applicare il modello di ridenominazione.

NOME

vidir: modifica la directory

SINOSSI

vidir [--verbose] [directory | file | -] ...

DESCRIZIONE

vidir consente la modifica dei contenuti di una directory in un editor di testo. Se non viene specificata alcuna directory, la directory corrente viene modificata.

Quando si modifica una directory, ogni elemento nella directory apparirà sulla propria riga numerata. Questi numeri indicano come vidir tiene traccia di quali elementi vengono modificati. Elimina le righe per rimuovere i file dalla directory o modifica i nomi dei file per rinominare i file. Puoi anche cambiare coppia di numeri per scambiare i nomi dei file.

Nota che se "-" viene specificato come directory da modificare, legge un elenco di nomi di file da stdin e visualizza quelli per la modifica. In alternativa, è possibile specificare un elenco di file sulla riga di comando.

ESEMPI

vidir vidir * .jpeg Usi tipici.

trova | vidir - Modifica anche i contenuti della sottodirectory. Per eliminare le sottodirectory, eliminare tutto il loro contenuto e la stessa sottodirectory nell'editor.

trova-tipo f | vidir: modifica tutti i file nella directory e nelle sottodirectory correnti.

AUTORE

Joey Hess 2006-2010

Modifiche di Magnus Woldrich 2011

DIRITTO D'AUTORE

Copyright 2006-2011 il vidir "AUTORE" come sopra elencato.

Licenza sotto GNU GPL.


0

Su un * nix senza perl renamedisponibile

Su alcuni * nix non è disponibile la ridenominazione, quindi è necessario effettuare la ridenominazione utilizzando un altro metodo. Alcuni anni fa ho suggerito zmvqui che, sebbene fantastico, non è necessariamente disponibile.

Usando builtin e sed, possiamo rapidamente creare uno script shell per fare ciò che ci dà una sintassi molto simile allo script perl rename, mentre manca un po 'di errore nella gestione della gentilezza, fa il lavoro.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

uso

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Supponiamo di voler creare anche cartelle di destinazione ...

Dal momento mvche non crea cartelle che non possiamo usare sedrenamecome è qui, ma è una modifica abbastanza piccola, quindi immagino che sarebbe bello includerlo anche.

Abbiamo bisogno di una funzione di utilità abspath(o percorso assoluto) in modo da poter generare le cartelle di destinazione per un modello sed / rename che includa la nuova struttura di cartelle.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

Questo ci assicurerà di conoscere i nomi delle nostre cartelle di destinazione. Quando rinomineremo dovremo usarlo sul nome del file di destinazione.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Ecco lo script completo per le cartelle ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Ovviamente, funziona ancora anche quando non abbiamo cartelle di destinazione specifiche.

Se volessimo mettere tutte le canzoni in una cartella, ./Beethoven/possiamo farlo:

uso

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Round bonus ...

Utilizzando questo script per spostare i file dalle cartelle in una singola cartella:

Supponendo che volessimo raccogliere tutti i file corrispondenti e posizionarli nella cartella corrente, possiamo farlo:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Nota sui modelli di sedge regex

In questo script si applicano le normali regole del modello sed, questi modelli non sono PCRE (espressioni regolari compatibili Perl). Potresti avere esteso la sintassi delle espressioni regolari, usando una sed -ro in sed -E base alla tua piattaforma.

Vedere la norma POSIX man re_formatper una descrizione completa dei modelli regexp di base ed estesi sed.

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.