Come posso usare rinomina per rinominare ricorsivamente ogni cosa in maiuscolo


11

Vorrei rinominare in modo ricorsivo tutti i file e le cartelle (sottocartelle) in maiuscolo.

Ho trovato alcuni script che lo faranno in minuscolo, ma non so come cambiarli, quindi lo farà al contrario (dal basso verso l'alto).

Lo script che ho trovato e funziona in minuscolo, ma non sapevo come modificarlo è:

rename 'y/A-Z/a-z/' *

Viene da man rename.


Senza sapere nulla del comando rename, sospetto che se ci provi rename 'y/a-z/A-Z/' *otterrai quello che vuoi. Attento a dove lo provi.
Warwick,

non è ricorsivo (perché quello iniziale non era ...) ma funziona. Non riesco a capire perché non ho pensato a quel miself :), grazie!
jnhghy - Alexandru Jantea,

Penso che, data la qualità della risposta di Gilles, sarebbe positivo se accetti la sua risposta preferibilmente alla mia. È molto più completo del mio e spiega le tue opzioni (e come funziona tutto). Grazie.
Warwick,

Risposte:


8

Nota che stai usando lo script Perl chiamatorename distribuito da Debian e derivati ​​(Ubuntu, Mint, ...). Altre distribuzioni Linux forniscono un comando completamente diverso, e molto meno utile, chiamato rename.

y/A-Z/a-z/traduce ogni carattere nell'intervallo Aattraverso Znel carattere corrispondente nell'intervallo aattraverso z, cioè ASCII maiuscoli lettere alla lettera minuscola corrispondente. Per eseguire la traduzione opposta, utilizzare y/a-z/A-Z/. Un altro modo per scrivere lo stesso comando è rename '$_ = uc($_)' *ucè la funzione u pper c ase e il renamecomando rinomina i file in base alla trasformazione effettuata nella $_variabile.

rename '…' *rinomina solo i file nella directory corrente, perché è quello che *corrisponde. Anche i file Dot (file il cui nome inizia con .) vengono saltati.

Se si desidera rinominare i file nella directory corrente e nelle sottodirectory ricorsivamente, è possibile utilizzare il findcomando per attraversare ricorsivamente la directory corrente. Qui c'è una difficoltà: se chiami rename, questo rinomina sia la directory che la parte del nome di base. Se si chiama renameuna directory prima di ricorrere in essa ( find -exec rename … {} \;), findviene confuso perché è stata trovata una directory ma tale directory non esiste più quando tenta di discenderla. Si può ovviare a questo dicendo findad attraversare una directory prima di agire su di esso, ma poi si finisce per cercare di cambiare titolo foo/baral FOO/BARma la directory FOOnon esiste.

Un modo semplice per evitare questa difficoltà è far sì che il comando di ridenominazione agisca solo sulla parte del percorso del nome base. L'espressione regolare ([^/]*\Z)corrisponde alla parte finale del percorso che non contiene a /.

find . -depth -exec rename 's!([^/]*\Z)!uc($1)!e' {} +

La shell zsh offre funzionalità più convenienti per la ridenominazione, ancora più criptiche di Perl, ma più terse e spesso più facili da comporre.

La funzione zmvrinomina i file in base a motivi. Esegui autoload -U zmvuna volta per attivarlo (inserisci questa riga nel tuo .zshrc).

Nel primo argomento di zmv(il modello da sostituire), puoi usare i potenti modelli jolly di zsh . Nel secondo argomento di zmv(il testo sostitutivo), è possibile utilizzare le sue funzioni di espansione dei parametri , inclusi i modificatori della cronologia .

zmv -w '**/*' '$1$2:u'

Spiegazione:

  • -w - assegna automaticamente variabili numeriche a ciascun modello jolly
  • **/*- tutti i file nelle sottodirectory, in modo ricorsivo ( **/corrisponde a 0, 1 o più livelli di sottodirectory)
  • $1 - la prima variabile numerica, qui corrispondente alla parte della directory di ciascun percorso
  • $2:u- la seconda variabile numerica, qui corrispondente alla parte del nome di base di ciascun percorso, con il :umodificatore per convertire il valore in maiuscolo

Come bonus aggiuntivo, questo rispetta le impostazioni locali dell'ambiente.

Se non sei sicuro di un zmvcomando che hai scritto, puoi passare l' -nopzione per stampare cosa farebbe il comando e non cambiare nulla. Controlla l'output e, se fa ciò che desideri, riesegui il comando senza -nagire effettivamente.


5

Rubato (con una modifica minore) dal post di Gilles qui

find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +


Questo non agisce in modo ricorsivo.
Gilles 'SO- smetti di essere malvagio' il

Vero. Avrei dovuto leggere correttamente la domanda. Non ho accesso al comando di ridenominazione, ma credo che funzionerà in modo ricorsivo -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Warwick

È un po 'più complicato di così, perché stai rinominando le directory mentre findricorre in esse.
Gilles 'SO- smetti di essere malvagio' il

@Gilles - OK. Dopo aver fatto un po 'di ricerca, sembra che sia necessario aggiungere l'opzione -depth per trovare in modo che i nomi delle directory vengano gestiti per ultimi. Quindi find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;dovrebbe gestire il problema delle directory di ridenominazione. Corretta?
Warwick,

No, che fa ancora non lavoro, perché renamele modifiche ad esempio foo/barper FOO/BARe FOOnon esiste in quel punto.
Gilles 'SO- smetti di essere malvagio' il

2

Vorrei indirizzare chiunque sia ancora legato a questa risposta all'eccellente risposta che Guiles Quernot ha dato a questa domanda che non richiede find.

Il comando risultante sarebbe:

shopt -s globstar
rename -n 'y/a-z/A-Z/' **

Ma prima di correre, leggi la risposta collegata per avvertenze riguardanti le vecchie versioni di bash.

Infine, nel caso qualcuno si stia chiedendo cosa fa il y///comando perl regex. Ecco un link alla documentazione pertinente .


1

find -execdir| rinominare

Questo sarebbe il modo migliore per farlo se non fosse per la follia del percorso relativo, in quanto evita che Perl regex fu agisca solo sul nome di base:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\U$1/' '{}' \;

-execdirprima cdnella directory prima di eseguire solo il nome di base.

Sfortunatamente, non riesco a liberarmi di quella PATHparte di hacking, mi find -execdirrifiuto di fare qualsiasi cosa se hai un percorso relativo in PATH...: /ubuntu/621132/why-using-the-execdir-action- è-insicuro-per-directory-che-è-in-the-path / 1.109.378 1.109.378 #


0

Prova questo dopo esserti spostato nella directory in cui desideri rinominare i file:

for word in `ls -ltr |tail -n +2 |awk '{print $9}'`
do
  a=$(echo $word | tr '[a-z]' '[A-Z]')
  mv $word $a
  echo "Done Successfully"
done

Non analizzare l'output di ls (e perché mai correresti ls -lsolo per tagliare le colonne diverse dal nome?), E usare le doppie virgolette attorno alle sostituzioni variabili . Il codice è eccessivamente complesso e si interrompe sui nomi dei file contenenti spazi bianchi e altri caratteri speciali. Utilizzare findo **/per ricorrere in sottodirectory, l'output di lsè solo per il consumo umano.
Gilles 'SO- smetti di essere malvagio' il
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.