Executando verificação de segurança...
2

[PowerShell] O Script de Renomeação de arquivos mais PPTO que você verá um inciante fazer hoje 😃

Fala pessoal! ✌😉

Antes de mais nada, gostaria de esclarecer que não tenho um entendimento muito profundo sobre PowerShell, tudo que fiz foi pesquisar na internet e ler a documentação sobre o assunto que precisava e praticar bastante até alcançar o resultado que mostrarei abaixo.

Pode ser que haja maneiras mais fáceis ou mais eficientes de chegar nesse mesmo resultado, mas eu estou aqui fazendo esse post justamente pelo fato de não ter encontrado um conteúdo de fácil acesso e tão "Pau Pra Toda Obra" quanto esse.
Ficarei muito feliz se puderem compartilhar alguma idéia para deixar o código ainda melhor.

Agora mostrarei o script e após dar o contexto de algumas coisas explicarei linha a linha todo o código.

A intenção é deixar tudo o mais claro possível até para quem não entende de PowerShell ou está iniciando em programação como eu.

O Script 📝

$textInfo = (Get-Culture).TextInfo #Necessario para o uso do ToTitleCase()

$path = "D:\Pasta dos Alunos\Turma [0-9]*\Word\"
$string = (Get-ChildItem -Path $path -Recurse).FullName
$regex = "^.+8.+-\s*([\w\s]*)\.docx$"

foreach ($i in $string){
    if($i -match $regex){
        $aux = $Matches.1
        $aux = $aux.ToLower()
        $aux2 = $textInfo.ToTitleCase($aux)
        $name = $aux2 -replace '[\s]{2,}', ' '
        
        Rename-Item -Path $i -NewName "Aula 08 - Avaliação Word - $name.docx"
    }
 }

Contexto 🎤

Pode ser que fique confuso o propósito do script, o que o Regex está fazendo e também o texto pelo qual o Rename-Item está trocando o nome dos arquivos.

Mas a explicação pra isso tudo é simples: Eu sou Professor de Informática e tenho alguns alunos um pouquinho ✨preguiçosos✨ na hora de salvar o nome do arquivo.

E com a inteção de deixar todos os nomes de arquivos das aulas mais bem organizados e legíveis eu desenvolvi esse script.

Mas eu tentei escrevê-lo de uma maneira que fosse fácil de adptar pra outras ocasiões em que se faça necessário o uso de um Regex e um tratamento de string para padronizar o resultado.

Agora deixa eu explicar direitinho o propósitdo de cada linha

Explicação 🗣

  • $textInfo está instanciando o objeto TextInfo que será necessário para usar o método ToTitleCase(), que por sua vez, servirá para colocar o nome do aluno extraído pelo Regex em "Modo Title". Não é necessário para o funcionamento, mas com certeza deixa mais legível o nome do arquivo.

  • $path é onde você pode passar o endereço da(s) pasta(s) que se encontram os arquivos a serem renomeados. E como você pode ver, o PowerShell também aceita Regex nesses casos.

  • $string está utilizando o cmdlet Get-ChildItem para obter uma lista contendo o endereço completo de cada arquivo. Note o método .Fullname ao final, ele garante que o nome do arquivo será retornado desde sua raíz (Ex: C:...) até sua extensão (Ex: ....docx) isso será importante para alimentar o parâmetro -Path do Rename-Item mais a frente.

  • $regex Por fim, nesta variável eu passo meu padrão Regex que encontra arquivos que sejam parecidos com "aula08-avaliacao word-nome do sujeito.docx". Você pode usar o site regex101 para treinar e construir o padrão Regex que precisar. Inclusive você pode usar este nome do arquivo de exemplo e o Regex da variável para começar a entender como funciona. Você notará que "nome do sujeito" ficara destacado.

foreach

Aqui dentro temos o if que vai verificar arquivo por arquivo e prosseguir com o tratamento nos que derem match com o padrão Regex.

$aux = $Matches.1

Nesta linha é onde capturamos nome do aluno presente no arquivo. Então seguindo o exemplo anterior, se o nome do arquivo for "aula08-avaliacao word-nome do sujeito.docx" ele conseguirá capturar o "nome do sujeito". E se você conseguiu fazer o teste no site regex101 deve ter notado que "nome do sujeito" ficou em uma cor destacada do resto do nome do arquivo.

(OBS: as proximas 3 linhas são apenas para deixar o nome capturado padronizado. Se você quiser apagá-las, substitua $aux = $Matches.1 por $name = $Matches.1 )

$aux = $aux.ToLower()

Neste caso, estamos fazendo com que o nome do aluno capturado fique com todas as letras em minúsculas. (Ex.: NoMe dO suJEItO --> nome do sujeito.)

$aux2 = $textInfo.ToTitleCase($aux)

Agora com o nome extraído, com todas as letras em minúsculas e armazenado na variável $aux, passamos ela dentro do método ToTitleCase(). E como havia dito, esse não é um passo crucial em todo caso de renomeação de arquivos, pois pode ser preferível até manter todas as letras minúsculas. (Ex.: nome do sujeito --> Nome Do Sujeito)

$name = $aux2 -replace '[\s]{2,}', ' '

Utilizei a função -replace para que pudesse retirar os espaços a mais que o usuário possa ter digitiado na hora de escrever o próprio nome. (eu sei... Mas acontece bastante 😴)
(Ex.: Nome Do Sujeito --> Nome Do Sujeito.)

Rename-Item

Por fim temos o Cmdlet Rename-Item onde passamos a variável $i, que contém o endereço completo de cada arquivo, no parâmetro -Path. E em seguida no o parâmetro -NewName, você pode colocar o novo nome do arquivo passando a variável $name onde se encaixar melhor.

Carregando publicação patrocinada...
2
$path = "D:\Pasta dos Alunos\Turma [0-9]\Word"
$regex = "^.+8.+-\s([\w\s]*).docx$"
Get-ChildItem -Path $path -Recurse | ForEach-Object {
if($.FullName -match $regex) {
$name = $Matches[1].Trim().ToLower()
$name = $textInfo.ToTitleCase($name)
$name = $name -replace '\s+', ' '
$newName = "Aula 08 - Avaliação Word - $name.docx"
Rename-Item -Path $.FullName -NewName $newName
}
}

so dando uma mudada aqui e ali, mas nao sei se é o resultado esperado. roda ai e me diz.

1

Sim, realmente chega no mesmo resultado. Obrigado por mostrar um método utilizando Pipelines. Eu tentei fazer algo utilizando Pipe mas não tava encontrando referência nem entendendo direito como funciona, mas ficou bem claro no seu código.

Apenas duas observações:

  • corrigi $.Fullname --> $_.Fullname para funcionar. Mas deu certinho.

  • E só um detalhezinho no regex do $path na parte da "Turma [0-9]". É que se faltar o * ele só encontra se houver 1 digito. E no caso de houver por exemplo Turma 23 acredito que não encontraria. (Ou poderia ser também um + ao invés de *)

Mas foi só isso até onde consegui observar.
Valeu demais!

1