Rinomina per avviare maiuscole o maiuscole iniziali in Bash


3

Ho bisogno di un oneliner per rinominare tutti i file in una directory da

SomeThing.TXT
NOT A FILE.ogg
sensibile lalala.doc

a

Something.txt
Not A File.ogg
Sensibile Lalala.doc

In altre parole: le prime lettere delle parole sono maiuscole e tutto il resto è minuscolo. Questo si chiama caso iniziale o maiuscolo iniziale . È molto vicino al "caso del titolo". L'estensione del file deve essere minuscola.

La maggior parte delle domande esistenti sembrano riguardare solo i nomi di file UPPERCASE.MKV o lowercase.mkv , nessuna sembra coprire Capitalized Case.mkv ( esempio ).

Tutti gli strumenti comuni come tubi, sed, perl, grepe altro ancora possono essere utilizzati.


Quale Linux stai usando? È basato su Debian?
terdon,

@terdon Arch Linux, ma teniamolo abbastanza portatile per non importare. :)
qubodup

Mi chiedo solo quale sia il tuo rename. È quello perl su Arch o quello su BSD?
terdon,

Il pacchetto proprietario di /usr/bin/renameè util-linux. perl-renameè un comando separato con un pacchetto con lo stesso nome.
qubodup,

Sì, molti sistemi vengono forniti con quello util-linux come predefinito. Bene, se hai perl-rename, puoi usare la mia risposta. Sul mio Debian, afferma di avvertire prima di sovrascrivere, ma in realtà non lo fa. Ho anche aggiunto una versione shell che può evitare la sovrascrittura.
terdon,

Risposte:


2

Se hai accesso a perl rename, (installato di default come renamesu sistemi basati su Debian, disponibile come perl-renamesu molti altri), puoi eseguire:

rename  's/.*/lc($&)/e; s/(^| )./uc($&)/ge' *

Spiegazione:

Il renameprogramma eseguirà un'espressione perl su ciascuno dei suoi nomi di file di input. Qui, la prima operazione di sostituzione ( s///) sostituirà tutto ( .*) con se stesso ( $&è qualunque cosa sia stata abbinata) ma con il maiuscolo ( lc($&)). Il secondo, abbinerà ogni carattere che segue uno spazio o all'inizio del nome del file ( (^| )) e lo sostituirà con la sua versione maiuscola ( uc($&)).

Esegui con il -nflag per testare senza apportare modifiche:

$ rename -n 's/.*/lc($&)/e; s/ ./uc($&)/ge' *
rename NOT A FILE.ogg not A File.ogg
rename sensitive lalala.doc sensitive Lalala.doc
rename SomeThing.TXT something.txt

Puoi anche usare un loop shell e perl:

for f in *; do 
    mv "$f" "$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")"
done

Questo è lo stesso comando di cui renamesopra, solo noi lo alimentiamo ogni file nella directory e usiamo la sostituzione dei comandi per rinominare.

Puoi facilmente modificarlo per evitare di sovrascrivere i file esistenti:

for f in *; do 
    target="$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")"; 
    [ -e "$target" ] && 
        echo "File \"$target\" exists, skipping \"$f\"" || 
        mv "$f" "$target"; 
done

L'ultimo script funziona davvero bene. Sfortunatamente su Ubuntu (LTS 14.04.4 LT) la prima riga proposta genera errori con nome con spazi ... ( /usr/bin/renamecollegamento /etc/alternatives/renamesimbolico a /usr/bin/prenamecollegamento simbolico a ; file perl RCSfile: rinominare, v Revisione: 4.1).
Hastur,

1

"Decapitalizzazione" ha risposto qui :

for i in *
do
  mv "$i" "$( echo $i | tr '[:upper:]' '[:lower:]')"
done

Le maiuscole hanno già risposto qui :

for i in *
do
  mv "$i" "$( echo $i | sed 's/[ ]*/\u&/g')"
done

Si prega di non pubblicare risposte solo link. Anche se il collegamento punta ad altri siti sulla rete SE. Invece, copia le informazioni pertinenti nella tua domanda o scrivi una risposta a questa domanda, in base alle informazioni lì.
terdon,

Riassumi la risposta collegata.
salutò il

1

Funziona su Bash 3.2.57Mac OSX

Anteprima (non cambia nulla):

IFS=$'\n';FOLDER=new;for F in $(ls -1);do EXT="${F##*.}";NAME="${F%.*}";NEW=$(echo "$NAME"| perl -pe 's/[ _-]([A-z0-9])([^ _-]+)/ \U\1\L\2/g');echo "cp '$F' '$FOLDER/$NEW.$EXT'";done

Se l'anteprima sembra buona, puoi usarla per rinominare e cp nella sottocartella:

IFS=$'\n';FOLDER=new;[ -d $FOLDER ] || mkdir $FOLDER;for F in $(ls -1);do EXT="${F##*.}";NAME="${F%.*}";NEW=$(echo "$NAME"| perl -pe 's/[ _-]([A-z0-9])([^ _-]+)/ \U\1\L\2/g');cp -v "$F" "$FOLDER/$NEW.$EXT";done

Gli appunti:

  • Non cambierà l'estensione del file.
  • Dovrebbe gestire i numeri correttamente.
  • Se hai altri caratteri che vuoi convertire in spazi, aggiungili alla classe di caratteri: [ _-]
  • Evita i nomi in conflitto facendo una copia di ogni file in una sottocartella. Questo ti dà un'opzione "annulla". Un altro modo per gestire questo sarebbe rinominare tutti i file, aggiungendo un prefisso come _My New File Name.jpg, quindi rinominare tutti quelli con le versioni senza il _.

Sfortunatamente, questo non sembra rinominare il primo carattere di un nome di file.
qubodup,

1

Ho trovato una soluzione rapida in una sola riga:

for f in *; do mv -i "$f" "`echo $f | sed -e 's/\(.*\)/\L\1/' -e 's/\( .\)/\U\1/g' -e 's/\(^.\)/\U\1/g'`"; done

O in forma leggibile (ma leggermente meno comodo per copiare il modulo incolla):

for f in *; do 
    mv -i "$f" "`echo $f | 
     sed -e 's/\(.*\)/\L\1/' -e 's/\( .\)/\U\1/g' -e 's/\(^.\)/\U\1/g'`"; 
done

Questo comando utilizza sedper mvogni file in un file con lo stesso nome ma in cui tutti i caratteri sono dapprima trasformato in lettere minuscole , ciascuna combinazione di spazio seguito da qualsiasi carattere è attivata in maiuscolo, maiuscolo quindi il primo carattere è acceso.

Questo chiederà prima di sovrascrivere.

Rimuovi -ise desideri che venga sovrascritto automaticamente.

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.