GNU/Linux >> Linux Esercitazione >  >> Linux

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

So che non è esattamente quello che volevi, ma se conosci la codifica originale, forse puoi usare convmv per modificare 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 .

Nota che questo comando in realtà non rinomina nulla; aggiungi --notest opzione per rinominare veramente i file.


Incontrerai qualche problema se vorrai rinominare i file e directory contemporaneamente. Rinominare solo un file è abbastanza facile. Ma vuoi assicurarti che anche le directory vengano rinominate. Non puoi semplicemente mv Motörhead/Encöding Motorhead/Encoding dal Motorhead non esisterà al momento della chiamata.

Quindi, abbiamo bisogno di una prima traversata approfondita di tutti i file e le cartelle, quindi rinominare solo il file o la cartella corrente. Quanto segue funziona con GNU find e 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

Puoi modificare la regex usando new="${f//[\\\/\:\*\?\"<>|]/}" se vuoi sostituire qualcosa 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 fa le giuste sostituzioni, rimuovi il echo dallo script per rinominare effettivamente le cose invece di limitarsi a stampare quello che fa.

Per sicurezza, ti consiglio di testarlo prima su un piccolo sottoinsieme di file.

Spiegazione delle opzioni

Per spiegare cosa succede qui:

  • -depth assicurerà che le directory siano ricorse in profondità, quindi possiamo "arrotolare" tutto dalla fine. Di solito, find attraversa in modo diverso (ma non in ampiezza).
  • -print0 garantisce il find l'output è delimitato da null, quindi possiamo leggerlo con read -d '' nel file variabile. Ciò ci aiuta a gestire tutti i tipi di nomi di file strani, inclusi quelli con spazi e persino le nuove righe.
  • Otteniamo la directory del file con dirname . Non dimenticare di citare sempre correttamente le tue variabili, altrimenti qualsiasi percorso con spazi o caratteri glob interromperebbe questo script.
  • Otteniamo il nome effettivo del file (o il nome della directory) con basename .
  • Quindi, rimuoviamo qualsiasi carattere non valido da $f utilizzando le capacità di sostituzione delle stringhe di Bash. Non valido significa qualsiasi cosa che non sia una lettera minuscola o maiuscola, una cifra, una barra (\/ ), un punto (\. ), un trattino basso o un trattino meno.
  • Se $f è già pulito (il nome pulito è identico al nome corrente), saltalo.
  • Se $new esiste già nella directory $d (ad esempio, hai file denominati resume e résumé nella stessa directory), emette un avviso. Non vuoi rinominarlo, perché, su alcuni sistemi, mv foo foo causa un problema. Altrimenti,
  • Alla fine rinominiamo il file originale (o la directory) con il suo nuovo nome

Poiché questo agirà solo sulla gerarchia più profonda, rinominando Motörhead/Encöding a Motorhead/Encoding avviene in due fasi:

  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 di test

Supponiamo 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 un'esecuzione in modalità debug (con echo davanti al 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é

Notare l'assenza di messaggi per with-hyphen.txt , schedule e test stesso.


Linux
  1. Come crittografare i file con gocryptfs su Linux

  2. Come convertire file in codifica UTF-8 in Linux

  3. Come rinominare più file usando Trova?

  4. Come posso rinominare i file con spazi utilizzando la shell di Linux?

  5. Come rimuovere i caratteri non validi dai nomi dei file?

Come rinominare uno o più file in Linux

Come sincronizzare i file con Unison su Linux

Come rimuovere file con estensione specifica in Linux

Come trovare file con il comando fd in Linux

Come caricare file con FileZilla

Come rinominare tutti i file con caratteri speciali e spazi in una directory?