Como posso usar renomear para renomear recursivamente tudo para maiúsculas


11

Gostaria de renomear recursivamente todos os arquivos e pastas (subpastas) para maiúsculas.

Encontrei alguns scripts que o fazem em minúsculas, mas não sei como alterá-los, portanto, o fazemos de outra maneira (de baixo para cima).

O script que encontrei e funciona para letras minúsculas, mas não sabia como modificar é:

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

É de man rename.


Sem saber nada sobre o comando renomear, suspeito que, se você tentar rename 'y/a-z/A-Z/' *, conseguirá o que deseja. Cuidado onde você testá-lo.
Warwick

não é recursivo (porque o inicial não era ...), mas funciona. Não consigo entender por que não pensei nisso :) :), então!
Jnhghy # Alexandru Jantea 07/07

Penso que, dada a qualidade da resposta de Gilles, seria bom se você aceitasse a resposta dele em preferência à minha. É muito mais completo que o meu e explica suas opções (e como tudo funciona). Obrigado.
Warwick

Respostas:


8

Note que você está usando o script Perl chamadorename distribuído pelo Debian e derivados (Ubuntu, Mint,…). Outras distribuições Linux oferecem um comando completamente diferente e consideravelmente menos útil chamado rename.

y/A-Z/a-z/traduz cada personagem na faixa Aatravés Zpara o personagem correspondente na faixa aatravés z, ou seja ASCII maiúsculas cartas para a letra minúscula correspondente. Para executar a tradução oposta, use y/a-z/A-Z/. Outra maneira de escrever o mesmo comando é rename '$_ = uc($_)' *ucé a função u cper c ase, e o renamecomando renomeia os arquivos com base na transformação feita na $_variável.

rename '…' *renomeia apenas os arquivos no diretório atual, porque é isso que *corresponde. Os arquivos de ponto (arquivos cujo nome começa com .) também são ignorados.

Se desejar renomear arquivos no diretório atual e nos subdiretórios recursivamente, você pode usar o findcomando para percorrer o diretório atual recursivamente. Há uma dificuldade aqui: se você ligar rename, isso renomeia o diretório e a parte do nome base. Se você chamar renameum diretório antes de retornar a ele ( find -exec rename … {} \;), findficará confuso porque encontrou um diretório, mas esse diretório não existe mais no momento em que tenta descer para ele. Você pode contornar isso, dizendo findque atravessar um diretório antes de agir sobre ele, mas depois você acaba tentando mudar o nome foo/barpara FOO/BARmas o diretório FOOnão existe.

Uma maneira simples de evitar essa dificuldade é fazer com que o comando de renomeação atue apenas no nome base como parte do caminho. A expressão regular ([^/]*\Z)corresponde à parte final do caminho que não contém a /.

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

O shell zsh fornece recursos mais convenientes para renomear - ainda mais enigmáticos que o Perl, mas mais tersos e geralmente mais fáceis de compor.

A função zmvrenomeia arquivos com base em padrões. Execute autoload -U zmvuma vez para ativá-lo (coloque esta linha na sua .zshrc).

No primeiro argumento para zmv(o padrão a ser substituído), você pode usar os poderosos padrões curinga do zsh . No segundo argumento para zmv(o texto de substituição), você pode usar seus recursos de expansão de parâmetros , incluindo modificadores de histórico .

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

Explicação:

  • -w - atribuir variáveis ​​numéricas automaticamente a cada padrão curinga
  • **/*- todos os arquivos em subdiretórios, recursivamente ( **/corresponde a 0, 1 ou mais níveis de subdiretórios)
  • $1 - a primeira variável numérica, aqui correspondente à parte do diretório de cada caminho
  • $2:u- a segunda variável numérica, que corresponde aqui à parte do nome base de cada caminho, com o :umodificador para converter o valor em maiúsculas

Como um bônus adicional, isso respeita as configurações de local do ambiente.

Se você não tiver certeza sobre um zmvcomando que escreveu, pode passar a -nopção de imprimir o que o comando faria e não alterar nada. Verifique a saída e, se fizer o que deseja, execute novamente o comando sem -nrealmente agir.


5

Roubado (com uma edição menor) do post de Gilles aqui

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


Isso não age recursivamente.
Gilles 'SO- stop be evil'

Verdade. Eu deveria ter lido a pergunta corretamente. Eu não tenho acesso ao comando de mudança de nome, mas acredito que isso vai funcionar de forma recursiva -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Warwick

É um pouco mais complicado que isso, porque você está renomeando diretórios enquanto findestá recorrendo a eles.
Gilles 'SO- stop be evil'

@Gilles - OK. Depois de fazer um pouco de pesquisa, parece que preciso adicionar a opção-profundidade para encontrar, para que os nomes dos diretórios sejam tratados por último. Portanto, find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;deve lidar com o problema de renomear diretórios. Corrigir?
Warwick

Não, isso ainda não funciona, porque as renamemudanças , por exemplo, foo/barpara FOO/BARe FOOnão existem nesse ponto.
Gilles 'SO- stop be evil'

2

Gostaria de direcionar quem ainda está sendo vinculado a esta resposta à excelente resposta que Guiles Quernot deu a essa pergunta que não exige find.

O comando resultante seria:

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

Mas antes de executar, leia a resposta vinculada a advertências sobre versões antigas do bash.

Finalmente, caso alguém esteja se perguntando o que o y///comando faz perl regex. Aqui está um link para a documentação relevante .


1

find -execdir| renomear

Essa seria a melhor maneira de fazer isso, se não fosse pela loucura relativa do caminho, pois evita que o Perl regex fu atue apenas no nome da base:

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

-execdirprimeiro cds no diretório antes de executar apenas no nome da base.

Infelizmente, não consigo me livrar dessa PATHparte de hackers, find -execdirse recusa a fazer qualquer coisa se você tiver um caminho relativo em PATH...: /ubuntu/621132/why-using-the-execdir-action- é inseguro para o diretório que está no caminho / 1109378 # 1109378


0

Tente isso depois de mudar para o diretório em que você deseja renomear os arquivos:

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

Não analise a saída de ls (e por que você correria ls -lapenas para cortar as colunas que não sejam o nome?) E use aspas duplas em torno das substituições de variáveis . Seu código é excessivamente complexo e quebra nos nomes de arquivos que contêm espaços em branco e outros caracteres especiais. Use findou **/recursione em subdiretórios, a saída de lsé apenas para consumo humano.
Gilles 'SO- stop be evil'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.