Newsgroup: it.comp.os.linux.iniziare
Titolo: [bash] Rinominare files in base a lista di nomi

Ho una directory che contiene 25 files mp3 nominati in modo bruttino e
casuale, hanno in comune la "desinenza" del tipo:
 
---
_01.mp3.
_02.mp3.
_03.mp3.
_04.mp3.
_05.mp3.
 
ecc ecc...
---
 
quei files sono le 25 traccie contenute in un album del quale ho
reperito la lista dei rispettivi titoli uno per riga in un file
di testo, che quindi ha una forma tipo:
 
---
1. Titolo Prima Traccia
2. Titolo Seconda
 
ecc ecc...
---
 
Quello che vorrei fare sarebbe banlmente rinominare ciascun
file assegnandogli il nome della corrispondente traccia che
si legge nel file di testo.
 
Faccio notare che ciò che conta è la posizione del file e
non il numero contenuto nel suo nome. Cioè dando un list
su una riga ecco che il primo file và associato alla prima
riga della lista, il secondo alla seconda e così via:
il numero di file da rinominare e il numero di righe della
lista dei rispettivi titoli sono identici.
 
Facciamo un esempio con 5 files: l'esempio chiarisce più di
tanti discorsi di solito.
 
Poniamo di avere i seguenti files nella dir di lavoro:
---
$ ls -1
file_pippo_01.mp3
file_pluto_03.mp3
file_paperino_04.mp3
file_paperone_11.mp3
file_minnie_20.mp3
---
 
E poniamo che la lista dei nomi delle tracce sia la seguente:
---
$ cat tracce.txt
1. titolo prima traccia
2. titolo seconda traccia
3. titolo terza traccia
4. titolo quarta traccia
5. titolo quinta traccia
---
 
Ok, lo scopo sarebbe rinominare ciascun file in modo che
danto un list i files mp3 siano nominati del tipo:
---
01. titolo prima traccia.mp3
02. titolo seconda traccia.mp3
03. titolo terza traccia.mp3
04. titolo quarta traccia.mp3
05. titolo quinta traccia.mp3
---
 
Una nota: siccome nel caso reale ci sono più di 10 tracce
gli "zero" all'inizio vanno aggiunti solo alle prime 9
in modo da avere una numerazione tipo:
---
01
02
03
...
09
10
11
12
ecc
---
 
Alla fine ho risolto con un po' di files di appoggio in cui ho
rediretto l'out di "ls -1", un po' di "paste", sed, tr e anche
un pizzico di editing manuale con vim.
 
Mi chiedevo però se c'era un sistema più automatico per farlo
in bash. Avevo iniziato a ragionare con gli arrai creandone
due (nomefile, nometraccia) ma gli spazi nei nomi delle tracce
hanno complicato le cose...
 
Scusate al lunghezza!!!  80

 ---
 
Sinceramente: io dall'esempio ho capito meno di prima. Comunque ti dico
che c'e' l'utility-comando "rename" che ottieni installando il pacchetto
con lo stesso nome. Dovrebbe risolverti tutto, solo che ci vuole
pazienza per capirla, ma tanto puoi fare tutte le prove che vuoi con
l'opzione "-n" in modo che ti dice cosa farebbe senza toccare nessun
file.
 
 
-- 
Tanti saluti
 


Ma rename serve per trovare pattern e di conseguenza fare le azioni
richieste.
Secondo me in questo caso non è possibile rinominare in base ad un
pattern perchè la rinomina non si basa tanto sul nome originario
dei files, quanto sulla loro posizione nell'ordinamento "alfabetico"
che ritorna ls (appunto l'esempio sopra era sbagliato: ls non
ordinerebbe così quei file nominati in quel modo.
 
Non hai tutti i torti quindi a non averci capito molto, proprio perchè
il comando "ls -1" non ritornerebbe i files di esempio ordinati in quel
modo... quindi ho sbagliato io a descrivere la cosa.
Lasciamo perdere WaltDisney và.... e fermiamoci a "pippo".
 
Ci riprovo...
---
 
Poniamo che i files siano originariamente nominati del tipo:
 
pippo_${NUMERO}.mp3
 
dove NUMERO assume valori da 01 in avanti, con la particolarità
che appunto i primi 9 numeri hanno lo zero davanti, i successivi
no:
 
01,02,03,04,05,06,07,08,09,10,11,12...
 
Inoltre alcuni numeri possono anche essere assenti...
 
Quindi abbiamo una directory contenete i nostri files mp3.
Se facciamo un list della directory poniamo di ottenere:
 
---
$ ls -1
pippo_01.mp3
pippo_05.mp3
pippo_13.mp3
pippo_22.mp3
pippo_25.mp3
$
---
 
D'altra parte abbiamo la lista dei nomi da associare a ciascun file:
 
---
cat titoli.txt
1. Prima Traccia
2. Seconda Traccia
3. Terza Traccia
4. Quarta Traccia
5. Quinta Traccia
---
 
Scopo del gioco:
voglio rinominare i files listati sopra in modo che:
 
- pippo_01.mp3 diventi "01. Prima Traccia.mp3"
- pippo_05.mp3 --->    "02. Seconda Traccia.mp3"
- pippo_13.mp3 --->    "03. Terza Traccia.mp3"
- pippo_22.mp3 --->    "04. Quarta Traccia.mp3"
- pippo_25.mp3 --->    "05. Quinta Traccia.mp3"
 
 
Spazi inclusi e zeri solo prima dei numeri da 1 a 9 inclusi:
nell'esempio sopra non si pone il problema perchè ci sono
solo 5 tracce ma nel caso reale ne ho 50... e gli zeri
iniziali vanno messi solo nel nome delle prime 9 tracce, non
nelle successive.
 
Spero che l'esempio sia più chiaro di prima...

 Spero che l'esempio sia più chiaro di prima...
 
Adesso l'esempio mi sembra chiarissimo. Se eviti gli assurdi ordinali e
il barbaro e schifoso spazio, e' facilissimo. Guarda:
 
----------- cut here ---------------
#! /bin/bash
 
let NUM=1
for j in $(ls); do
 
if [ $NUM -le 9 ]; then
mv $j 0$NUM.mp3
 
else
mv $j $NUM.mp3
fi
 
let NUM="$NUM + 1"
done
------------------------------
 
Questo te li muove in 01.mp3 eccetera, potresti anche optare per un nome
tipo: traccia-01.mp3 ... traccia-13.mp3  eccetera, basta modificare
appena lo script: 0$NUM.mp3  ->  traccia-0$NUM.mp3  e idem per l'altro.
 
 
-- 
Tanti saluti
 

 si legge nel file di testo.
 
ci sono diversi programmi per la gestione delle tag mp3 che fanno 
tutto questo molto facilmente (oltre a correggere tag eventualmente 
sbagliate)
 
cerca con google test comparativi e link dei vari programmi
-- 
bye
!(!1|1)


Nel mio caso gli mp3 li ho creati io:
sono il risultato di un album pubblicato come un'intero unico
mp3. Ho usato mp3splt per splittarlo in N tracce sfruttando
il basso volume tra una canzone e la successiva (opzione -s di
mp3splt).
 
In pratica quegli mp3 dovrebbero esser nudi e crudi senza alcun
tag aggiunto da chi li ha creati... se è questo che intendi.
Pertanto forse l'indicazione verso cui intendi indirizzarmi
potrebbe non essere la via più risolutiva.
 
Detto questo non smanetto spesso con mp3 e multimedia in genere
per cui ammetto d'essere piuttosto ignorante in materia. Se ti
pare che le tue indicazioni siano applicabili in qualche modo
anche a questo caso fammi pure sapere, altrimenti confermami
pure se effettivamente non sono utili per lo scopo.


Ok, ma questo è solo metà dell'opera...
Infatti io voglio che alla fine i files abbiano il nome pescato dalla
lista dei titoli.
Titoli che nell'esempio sono un po' generici (Prima Traccia, seconda
traccia ecc..). Ma nella realtà sono invece banalmente i titoli delle
canzoni che costituiscono l'album.
 
Ad esempio il tuo:
 
"01.mp3"
 
deve diventare uguale al primo titolo (la prima riga praticamente) del
file dei titoli titoli.txt. Che potrebbe essere ad esempio:
 
"1. Smell Like Teen Spirit"
 
Vado a caso eh...  ;D
Poi ci và aggiunto lo zero davanti e l'estensione .mp3 in coda in modo
che diventi alla fine:
 
"01. Smell Like Teen Spirit.mp3"

 lista dei titoli.
 
Si' l'avevo gia' capito dal post che t'ha scritto not1xor1, allora
mi spiace ma non me ne intendo ciao
 
 
-- 
Tanti saluti
 


Grazie comunque!  :)

 Detto questo non smanetto spesso con mp3 e multimedia
 
Se ho capito, prova a dividere il lavoro in piu' parti:
 
lista tutti i file e rinominali facendoli diventare 01.mp3, 02.mp3 etc etc
 
poi, per ogni file, fai cat (o leggi le righe) per estrarre il titolo, 
ricomponi quello nuovo e rinomini il file, tanto con pochi file cosi' se 
ci mette 1/10 di secondo in piu' non ti cambia la vita. Io ci darei, per 
tagliare i nomi e ricomporli, parecchio di cut.


Architecture: i386
Depends: libc6 (>= 2.3.5-1)
Description-it: rinomina file mp3 secondo i tag id3
 Mp3rename è un piccolo strumento per rinominare tutti quei file mp3 con un
 nome dato malamente.
 .
 Il nome file generato può essere basato sui tag id3; titolo, album, anno,
 traccia e/o artista.
Description-md5: 698ca7510b32c2678a2e38b0eec173da
Tag: interface::commandline, role::program, scope::utility, use::organizing,
 works-with-format::mp3, works-with::audio
Section: sound
Priority: optional
Filename: pool/main/m/mp3rename/mp3rename_0.6-9_i386.deb
Size: 8946
MD5sum: dd59edc1830c257a259768e9ddbc833a
SHA1: 508f5f2e4d36098d6a2d5874946f4dec9fae391b
SHA256: 8d68b87d7303c4ef503cf446ab20ba9f856ff1aaf444a8f63b97ee8712e0b987
-----------------------------------------------
 
-- 
Tanti saluti
 


Si, come dicevo nei primi post, ho in pratica già risolto proprio con
cut paste sed ecc...
Ma in modo semi automatico, perchè alla fine dovendo fare questa manovra
una volta sola ho fatto prima così che a starci a studiare troppo.
 
---
ls -1 > old
---
Questo crea una lista dei nostri file mp3 ordinati in ordine alfabetico
in base al nome originario. siccome non contengono spazi siamo anche
apposto così senza apici o altro.
 
---
sed "s/^/\'/;s/$\.mp3\'/" titoli.txt > new
---
Quest'altro prende il fiel dei titoli e ne crea una lista di nomi
da attrivbuire ai vari files comprensivi di apici in modo da preservare
gli spazi.
 
Mancano però gli "zeri" iniziali davanti ai primi 9 nomi.
Li ho banalmente aggiunti a mano con vim:
---
:s/^/0/9
---
 
che poi si poteva anche fare la stessa cosa più elegantemente con sed:
---
sed 1,9's/^/0/' titoli.txt
---
 
E mi viene in mente che si potrebbe anche già aggiungere un "mv" davanti
ai files in "old"... Soluzione definitiva, oqquasi:
 
---
ls -1 *mp3|sed 's/^/mv /' > old
sed "1,9s/^/0/;s/^/'/;s/$/.mp3'/" titoli.txt > new
paste old new > rename_rule
. rename rule
---
 
In pratica creiamo un script di rinomina in modo automatico e poi lo
eseguiamo con la bash attraverso l'operatore "."
Funziona?
 
Nel mio caso no, perchè alcunii titoli delle canzoni oltre gli spazi
contengono anche degli apostrofi che fanno a pugni con gli apici
per proteggere gli spazi.
Si può risolvere modificando il comando sed e aggiungendovi la rimozione
degli apici, al loro posto si può mettere uno spazio esempio:
---
sed "1,9s/^/0/;s/'/ /;s/^/'/;s/$/.mp3'/" titoli.txt > new
---
 
Con questa modifica funziona tutto.
Però è una soluzine un po' arzigogolata...
Se voleste provarla anche senza avere gli mp3 ecco una possibile
replica di quello che ho fatto poco fà per testare la faccenda.
Il file titoli.txt però dovrete riempirlo con la vostra lista di
canzoni e assegnare il numero totale delle tracce alla variabile
NTR (nel mio caso avevo 50 canzoni).
Occhio al "vim" per inserirle da dentro lo script.
 
Il "motore" del seguente script è fatto dalle ultime 5 righe.
quindi potete anche spezzarvi lo script in due ecc ecc...
 
---
#!/bin/sh
 
NTR=50
 
# creo l'ambiente di lavoro per il test
 
mkdir rinominatracce
cd rinominatracce
for (( i=1; i<=$NTR; i++ ))
do
	(( $i <= 9 )) && touch traccia_0$i.mp3|| touch traccia_$i.mp3
done
 
# Apro vim per incollarvi dentro la lista dei titoli
# copiatta dalla rete.
 
vim titoli.txt
 
# La parte precedente si può fare anche a mano e serve per
# automatizzare in parte la crazione di un ambiente di test.
# Si può tagliare e fare tutto a mano
 
ls *mp3|sed 's/^/mv /' > old
sed "1,9s/^/0/;s/'/ /;s/^/'/;s/$/.mp3'/" titoli.txt > new
paste old new > rename_rule
. rename rule
rm old new rename_rule
---
 
Boh, sembra anche abbastanza concisa come cosa,
ma non mi piace troppo. Forse perchè avevo in
mente di risolverla con degli array...
 
Voi cosa ne dite?

 
 
In questo caso mi sa che non ci farei molto perche gli mp3 in question e
non hanno praticamente tags:
 
---
$ mpg321 -t --long-tag traccia_01.mp3
[...]
 
Playing MPEG stream 1 of 1: bigbillbroonzy-theanthology_silence_01.mp3 ...
 
MPEG 1.0 layer III, VBR, 44100 Hz joint-stereo
 
        Title:
        Artist:
        Album:
        Year:
        Genre:
        Comment:
 
 
[2:56] Decoding of traccia-01.mp3 finished.
---
 
Nell'altro post ho spiegato come ho ottenuto quelle tracce.


che se usavi perl era piu facile e piu elegante
 

 potrebbe non essere la via più risolutiva.
 
imho usare le tag degli mp3 potrebbe essere utile specialmente se poi 
li vuoi usare su un altro lettore (tablet, cellulare, auto, ecc.)
 
ricordo vagamente che una quindicina di anni fa avevo buttato giù uno 
script (ma in OS/2 REXX, quindi non gira sotto linux e dovrei perdere 
qualche ora per ritrovarlo tra vecchi backup) che oltre a fare più o 
meno quello che ti serve (rinominare file mp3 leggendo i titoli da un 
file di testo) impostava le varie tag mp3
 
non sarebbe troppo complicato scrivere una cosa del genere in pyhton o 
simili linguaggi di alto livello, ma in questo periodo proprio non ho 
tempo
 
prova a cercare con google, sicuramente ci sarà qualcosa di pronto
-- 
bye
!(!1|1)
 
 

 Nell'altro post ho spiegato come ho ottenuto quelle tracce.
 
M'hai incuriosito con la storia di mp3splt, probabilmente lo script che
ti serve e' semplicissimo. Pero' devi dire qlc come:
 
1) Ho molte directory, in ognuna delle quali ci stanno molti file .mp3
 
2) Ecco l'esempio di due di tali directory:
---------------
ls carosone/
guaglione-03.mp3
maruzzella-13.mp3
-------------------
-----------------
ls modugno/
volare-07.mp3
ciao_bambina-39.mp3
----------------------
 
In altre parole il testo che dici da dove lo dovresti prendere?
Sai: io mi ci diverto a fare gli script:-)
 
 
-- 
Tanti saluti
 


Grazie delle indicazioni.
 
Tuttavia come dicevo è un'operazione che per quello che serve a me
non giustifica la stesura di uno script in altri linguaggi, per il
semplice motivo che non conosco abbastanza nè perl nè python.
E inoltre non penso di dover più fare una cosa del genere per molto
tempo...
 
Per carità non sarebbe un esercizio inutile anche a fini didattici e
a dirla tutta mi ero già riproposto di impararmi qualche rudimento di
perl, ma poi c'è sempre qualcosa di "prioritario" che mi fa rinunciare.
 
Tornando in bash, avevo posto la domanda perchè l'idea che mi era
venuta in mente per risolvere la questione era quella di utilizzare
due array:
- nel primo si caricano i files in modo ordinato alfabeticamente
- nel secondo si caricano i "records" della lista dei titoli che
  poi di fatto sono i titoli stessi.
 
Però poi mi sono scontrato con i vari problemi che la shell ha con
gli spazi gli apici ecc.
E come abbiamo visto conviene forse rimaneggiare dei file di testo
più che caricare dei valori come elementi di array, ripeto "forse".
 
Quindi a dirla tutta mi sarei aspettato una risposta in quella
direzione (array).

 Sai: io mi ci diverto a fare gli script:-)
 
 
 
Cosa intendi per "testo"?
La lista dei titoli?
 
Banalmente ho messo in google il titolo della compilation, ho
trovato una pagina in cui fosse descritto il contenuto e nello
specifico la lista delle tracce, quindi mi sono copia-incollato
la lista dei pezzi in un file di testo, usando l'editor di
testo: niente di chè...
 
Mi sa però che non ho capito bene il tuo esempio: io parto da
un unico MP3 (anzi era M4A a dire il vero, l'ho convertito con
ffmpeg se non ricordo male) che contiene tutto l'album.
 
Con mp3splt vengono "estratte" tutte le singole tracce nominate
tipo (Vedi mio post precedente).
 
Sono tutte in una singola directory e alcune sono relative
alla stessa canzone percchè mp3splt con l'opzione "-s" cerca
gli istanti in cui il volume è sotto una certa soglia e assume
quell'istante come fine della canzone. Quindi taglia l'mp3 in
quel punto.
Tuttavia non è detto che una canzone che magari ha un punto in
cui il volume scende sotto una ceta soglia non sia spezzata
generando due files mp3 in uscita. Nel mio caso è capitato un
paio di volte e ho riassemblato il tutto a mano: L'album doveva
contenere 50 brani mentre io avevo 53 files mp3 in uscita dallo
split.
 
Alla fine, hai N tracce mp3 nominate con una certa logica sì ma
non in modo preciso, infatti come è ovvio alcuni numeri vengono
saltati perchè se ad esempio al brano 7 corrispondono due tracce
che saranno sputate fuori come 07 e 08.
A quel punto le riassemblo e chiamo il file del brano totale per
esempio 07, ecco che quindi il 08 non ci sarà più tra i files da
rinominare.
 
 

 rinominare.
 
Allora devi postare:
 
1) Il testo completo che hai preso da google per uno degli album come
esempio.
 
2) Il nome della directory dove hai splittato l'album.
 
3) L'output di ls di tale directory.
 
4) Come vorresti rinominare i file mp3, cioe' se ti basta traccia-01.mp3
eccetera, o ve suoi il nome preso dal google-testo per ogni brano.
 
5) Dire se le directory-album sono talmente tante che non hai voglia di
usare a mano uno script entrando di volta in volta in ognuna di esse.
 
 
-- 
Tanti saluti
 

 usare a mano uno script entrando di volta in volta in ognuna di esse.
 
No, ve n'era una sola, ma con 50 brani da rinominare e farlo a mano non
mi andava...
 
LA cosa più semplice che mi era venuta in mente come ho gia detto era
usare due array uno per il nome dell'audiofile e uno per il titolo.
Caricati gli array bastava poi fare un qualcosa tipo:
 
---
 
for (( i=0 ; i<=finearray; i++))
do
	mv audiofile[$i] titolo[$i]
done
 
---
 
... è sicuramente sbagliato l'ho fatto al volo tanto per far capire
il senso, lasciate perdere la sintassi.
Nella mia prova con gli array però sono emersi parecchi problemi legati
agli spazi (e apici) presenti nei titoli.