Este script Powershell renomeará os arquivos da maneira que você precisar. Salve-o como RenameFiles.ps1
e execute a partir do console do PowerShell.
O script aceita os seguintes argumentos:
-
Caminho : Pasta exigida existente no disco, onde seus arquivos estão armazenados. Você pode fornecer vários caminhos.
-
Recurse : opção opcional, controla a recursão. Se especificado, o script renomeará os arquivos em todas as subpastas.
-
WhatIf : opção opcional, se especificado, o script relatará apenas nomes de arquivos novos e antigos. Nenhuma renomeação será feita.
Exemplos (executados no console do PowerShell):
-
Renomeie todos os arquivos na pasta c:\path\to\files
:
.\RenameFiles.ps1 -Path 'c:\path\to\files'
-
Renomeie todos os arquivos pdf
na pasta c:\path\to\files
:
.\RenameFiles.ps1 -Path 'c:\path\to\files\*.pdf'
-
Renomeie todos os arquivos pdf
na pasta c:\path\to\files
, recurse
.\RenameFiles.ps1 -Path 'c:\path\to\files\*.pdf' -Recurse
-
Verifica arquivos em várias pastas, recurse, reportar somente (sem renomear):
.\RenameFiles.ps1 -Path 'c:\path\A\*.pdf', 'c:\path\B\*.psd' -Recurse -WhatIf
RenameFiles.ps1
do próprio script:
# Arguments accepted by script
Param
(
# One or multiple paths, as array of strings
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string[]]$Path,
# Recurse switch
[switch]$Recurse,
# Whatif switch
[switch]$WhatIf
)
# This function transforms long file name (w\o extension) to short via regex
function Split-FileName
{
[CmdletBinding()]
Param
(
# Original file name
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$FileName
)
Begin
{
# You can change this block to adapt new rules for file renaming,
# without modifying other parts of script.
# Regex to match, capture groups are used to build new file name
$Regex = '(Sample2).*(\d{2}-\d{2}-\d{4}).*(?<=[a-z]_)(\d+)(?=_\d+).*(?<=_)(\d+)$'
# Scriptblock that builds new file name. $Matches is hashtable, but we need array for the format (-f) operator.
# So this code: @(0..$Matches.Count | ForEach-Object {$Matches[$_]})} transforms it to the array.
# Basically, we creating a new array of integers from 0 to count of $Matches keys, e.g. @(0,1,2,3,4,5)
# and passing it down the pipeline. Then, in the foreach loop we output values of $Matches keys which name
# match the current pipeline object, e.g. $Matches['1'], $Matches['2'], etc.
# $Matches['0'] holds whole matched string, other keys hold capture groups.
# This would also work:
# $NewFileName = {'{0}_{1}_{2}_{3}{4}' -f $Matches['1'], $Matches['2'], $Matches['3'], $Matches['4'], $Matches['5']
$NewFileName = {'{1}_{2}_{3}_{4}{5}' -f @(0..$Matches.Count | ForEach-Object {$Matches[$_]})}
}
Process
{
# If original file name matches regex
if($FileName -match $Regex)
{
# Call scriptblock to generate new file name
. $NewFileName
}
}
}
# For each path, get all file objects
Get-ChildItem -Path $Path -Recurse:$Recurse |
# That are not directory
Where-Object {!$_.PsIsContainer} |
# For each file
ForEach-Object {
# Try to create new file name
$NewBaseName = $_.BaseName | Split-FileName
if($NewBaseName)
{
# If file name matched regex and we've got a new file name...
# Build full path for the file with new name
$NewFullName = Join-Path -Path $_.DirectoryName -ChildPath ($NewBaseName + $_.Extension)
if(Test-Path -Path $NewFullName -PathType Leaf)
{
# If such file already exists, show error message
Write-Host "File already exist: $NewFullName"
}
else
{
# If not, rename it or just show report, depending on WhatIf switch
Rename-Item -Path $_.FullName -NewName $NewFullName -WhatIf:$WhatIf -Force
}
}
}
Regex usado neste script: link (observe que a regex do PowerShell por padrão não faz distinção entre maiúsculas e minúsculas). Cópia da explicação de regex aqui:
Regex :
(Sample2).*(\d{2}-\d{2}-\d{4}).*(?<=[a-z]_)(\d+)(?=_\d+).*(?<=_)(\d+)$
Sample2 string:
1st Capturing group (Sample2)
Sample2 matches the characters Sample2 literally (case insensitive)
Qualquer caractere (não capturado e não existe na variável $Matches
):
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible,
giving back as needed [greedy]
Data :
2nd Capturing group (\d{2}-\d{2}-\d{4})
\d{2} match a digit [0-9]
Quantifier: {2} Exactly 2 times
- matches the character - literally
\d{2} match a digit [0-9]
Quantifier: {2} Exactly 2 times
- matches the character - literally
\d{4} match a digit [0-9]
Quantifier: {4} Exactly 4 times
Qualquer caractere (não capturado e não existe na variável $Matches
):
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible,
giving back as needed [greedy]
Número de páginas :
(?<=[a-z]_) Positive Lookbehind - Assert that the regex below can be matched
[a-z] match a single character present in the list below
a-z a single character in the range between a and z (case insensitive)
_ matches the character _ literally
3rd Capturing group (\d+)
\d+ match a digit [0-9]
Quantifier: + Between one and unlimited times, as many times as possible,
giving back as needed [greedy]
(?=_\d+) Positive Lookahead - Assert that the regex below can be matched
_ matches the character _ literally
\d+ match a digit [0-9]
Quantifier: + Between one and unlimited times, as many times as possible,
giving back as needed [greedy]
Qualquer caractere (não capturado e não existe na variável $Matches
):
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible,
giving back as needed [greedy]
Número de ID :
(?<=_) Positive Lookbehind - Assert that the regex below can be matched
_ matches the character _ literally
4th Capturing group (\d+)
\d+ match a digit [0-9]
Quantifier: + Between one and unlimited times, as many times as possible,
giving back as needed [greedy]