Come rinominare in blocco i file con codifica non valida o sostituire in blocco i caratteri codificati non validi?


15

Ho un server debian e sto ospitando musica per una stazione radio su Internet. Ho dei problemi con i nomi e i percorsi dei file perché molti file hanno una codifica non valida, ad esempio:

./music/Bändname - Some Title - additional Info/B�ndname - 07 - This Title Is Cörtain, The EncÃding Not.mp3

Idealmente, vorrei rimuovere tutto ciò che non è lettere A-Z/ a-zo numeri 0-9o trattino -/ trattino basso _... Il risultato dovrebbe apparire come questo:

./music/Bndname-SomeTitle-additionalInfo/Bndname-07-ThisTitleIsCrtain,TheEncdingNot.mp3

Come ottenere questo risultato per un lotto di molti file e directory?

Ho visto questa domanda simile: rinominare in blocco (o visualizzare correttamente) file con caratteri speciali

Ma questo risolve solo la codifica, preferirei un approccio più rigoroso come descritto sopra.

Risposte:


14

Incontrerai alcuni problemi se vuoi rinominare file e directory allo stesso tempo. Rinominare solo un file è abbastanza semplice. Ma vuoi assicurarti che anche le directory vengano rinominate. Non puoi semplicemente mv Motörhead/Encöding Motorhead/Encodingperché Motorheadnon esisterà al momento della chiamata.

Quindi, abbiamo bisogno di un attraversamento approfondito di tutti i file e cartelle, quindi rinominare solo il file o la cartella corrente. Il seguente funziona con GNU finde Bash 4.2.42 sul mio OS X.

#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
  d="$( dirname "$file" )"
  f="$( basename "$file" )"
  new="${f//[^a-zA-Z0-9\/\._\-]/}"
  if [ "$f" != "$new" ]      # if equal, name is already clean, so leave alone
  then
    if [ -e "$d/$new" ]
    then
      echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
      ls -ld "$d/$new" "$d/$f"
    else
      echo mv "$file" "$d/$new"      # remove "echo" to actually rename things
    fi
  fi
done

È possibile modificare la regex utilizzando new="${f//[\\\/\:\*\?\"<>|]/}"se si desidera sostituire tutto ciò che Windows non è in grado di gestire.

Salva questo script come rename.sh, rendilo eseguibile con chmod +x rename.sh. Quindi, chiamalo come rename.sh /some/path.

Assicurati di risolvere eventuali collisioni di nomi di file (" Notice" annunci).

Se sei assolutamente sicuro di fare i giusti sostituti, rimuovi echolo script dallo script per rinominare le cose invece di stampare semplicemente quello che fa.

Per sicurezza, consiglierei prima di provare questo su un piccolo sottoinsieme di file.


Opzioni spiegate

Per spiegare cosa succede qui:

  • -depthassicurerà che le directory vengano ripetute in profondità in primo luogo, in modo da poter "arrotolare" tutto dalla fine. Di solito, findattraversa in modo diverso (ma non prima).
  • -print0assicura che l' findoutput sia delimitato da null, quindi possiamo leggerlo con read -d ''nella filevariabile. Ciò ci aiuta a gestire tutti i tipi di nomi di file strani, compresi quelli con spazi e persino le nuove righe.
  • Otterremo la directory del file con dirname. Non dimenticare di citare sempre correttamente le tue variabili, altrimenti qualsiasi percorso con spazi o personaggi sconvolgenti spezzerebbe questo script.
  • Otterremo il nome file attuale (o il nome della directory) con basename.
  • Quindi, rimuoviamo qualsiasi carattere non valido $fdall'uso delle funzionalità di sostituzione delle stringhe di Bash. Invalid indica qualsiasi cosa che non sia una lettera minuscola o maiuscola, una cifra, una barra ( \/), un punto ( \.), un carattere di sottolineatura o un trattino meno.
  • Se $fè già pulito (il nome pulito è identico al nome corrente), saltalo.
  • Se $newesiste già nella directory $d(ad esempio, hai i file con nome resumee résuménella stessa directory), emetti un avviso. Non vuoi rinominarlo, perché, su alcuni sistemi, mv foo foocausa un problema. Altrimenti,
  • Alla fine rinominiamo il file (o la directory) originale con il suo nuovo nome

Poiché questo agirà solo sulla gerarchia più profonda, la ridenominazione Motörhead/Encödingin Motorhead/Encodingviene eseguita in due passaggi:

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

Ciò garantisce che tutte le sostituzioni vengano eseguite nell'ordine corretto.


File di esempio ed esecuzione del test

Supponiamo che alcuni file in una cartella di base chiamata test:

test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule

Ecco l'output di una corsa in modalità debug (con il echodavanti a mv), ovvero i comandi che verrebbero chiamati e gli avvisi di collisione:

mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r--  …  …  test/work/resume
-rw-r—r--  …  …  test/work/résumé

Si noti l'assenza di messaggi per with-hyphen.txt, schedulee testper sé.


1
Potresti voler aggiungere la logica per gestire il caso in cui mvesiste già la destinazione del , che può accadere (1) se hai file già puliti (risultanti mv foo foo), o (2) se hai file con lo stesso nome tranne per i caratteri speciali (ad es. mv Encöding Encoding, dove hai già un Encodingfile in aggiunta a Encöding).
Scott,

Buona idea, grazie. Qualche suggerimento specifico su cosa fare in quel caso? Concesso: raggiungerlo in modo pulito e sano è più difficile di quanto sembri inizialmente. Se hai qualcosa, sentiti libero di modificare ovviamente.
Slhck,

Non credo che abbia senso pensare a gestire automaticamente le collisioni - basta identificarle per l'utente e lasciarle gestire. Ho modificato la tua risposta, come mi hai suggerito.
Scott,

+1 per usare l'esempio con "Encöding" Troppo fön! :-)
Marcel

Dopo tre anni torno ancora qui. così utile! :-)
Afr

15

So che non è esattamente quello che volevi, ma se conosci la codifica originale, forse puoi usare convmvper cambiare la codifica in UTF-8, che dovrebbe risolvere la maggior parte dei problemi.

Questo ha funzionato per me su una cartella con alcuni nomi di file polacchi con codifica non valida:

convmv -f cp1250 -t utf8 -r .

Si noti che questo comando in realtà non rinomina nulla; aggiungi --notestun'opzione per rinominare davvero i file.


1
Per coloro che hanno un set statico (o non hanno un mix diversificato di set di caratteri), l' convmvopzione è incredibilmente semplice e perfetta. Per OP, con una potenziale moltitudine di set di caratteri, questo potrebbe essere unito all'altra risposta, poiché convmvsembra sapere quando o quando non incontra il formato corretto. Passando attraverso i set di caratteri, tramite convmv --list, si otterrebbero correttamente codificati.

1
Con questo intendo, se, come OP, avvii un server Debian, oggi si supporrebbe certamente UTF8, nel qual caso si possono conservare le lettere originali. Avevo una cartella di alcuni caratteri nordici e usavo: convmv -t utf8 --nfc -f iso-8859-1 --notest -r .- --nfcEra conforme a Linux prima di OS X o giù di lì, semplicemente digitando si convmvrinunciavano alle (utili) opzioni.

0

Lo so, mi hai chiesto di rinominare.

Ma puoi schivare il problema abbastanza facilmente usando software come MusicBrainz Picard .

È in grado di identificare la musica (impronte digitali audio), scaricare tutti i dati necessari (comprese le immagini di copertina, ove disponibili) dall'enorme database MusicBrainz e spostare i file in modo che la tua collezione possa adattarsi a qualsiasi modello che ti piace. Lo sto usando da anni e ha sempre funzionato perfettamente con qualsiasi cosa, dal cirillico all'arabo; e ovviamente (almeno per gli script in latino) può anche fare la conversione in ASCII.

Con questo approccio non importa quanto sia davvero disordinata / mal denominata la tua collezione, purché i file siano leggibili e completi.

(Ho già detto che è gratuito? Sia come nella libertà di parola che nella birra gratuita? Sia il software che il database ..?)

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.