Preciso renomear muitos arquivos que contêm um nome e um número de crachá.
Os arquivos ficam assim: "John Doe 1234.txt" e devo renomeá-lo para 1234.txt
(o novo arquivo deve conter apenas o número do crachá).
Além disso, o número do crachá não é fixo, pode conter de 3 a 4 números.
Atualização: O nome do arquivo contém 2 a 3 nomes separados por espaços. Por exemplo: "John Doe 123.txt" ou "John Junior Doe 1234.txt"
Estava pensando em deletar todas as letras e espaços do nome e manter apenas os números, mas não conheço o Powershell suficientemente bem.
Alguém pode me ajudar?
Responder1
Nomes de arquivosnão podecontém caracteres especiais ( O CÓDIGO AGORA É INFALÍVEL./\:*?"<>|
), mas pode conter caracteres como %
e !
que podem causar cmd.exe
interceptação incorreta, portanto o código não é infalível.
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set "dir=YOUR DIRECTORY HERE"
set "_output="
set "map=0123456789"
pushd "%dir%"
FOR %%a in (*.txt) do (
SETLOCAL
set "file=%%~na"
1>temp.log echo(!file!
for %%b in (temp.log) do set /A len=%%~zb-2
del /F /Q temp.log
for /L %%A in (0 1 !len!) do (
for /F "delims=*~ eol=*" %%? in ("!file:~%%A,1!") do if "!map:%%?=!" NEQ "!map!" set "_output=!_output!%%?"
)
ren "!file!.txt" "!_output!.txt"
ENDLOCAL
)
ENDLOCAL
Observação: só pode lidar com até 31 arquivos, devido ao MINHA ASSUNÇÃO ESTAVA ERRADA.Ele pode lidar com arquivos infinitos, por causa dos SETLOCAL
SETLOCAL
arquivos ENDLOCAL
.
Responder2
Supondo que todos os nomes de arquivos estejam no formato "Primeiro Último Número.txt
Você pode correr:
pushd "C:\Temp\su\"
dir | ? { $_.Name -like "*.txt" } |
% { Rename-Item $_ "$($_.BaseName.split(' ')[2])$($_.Extension)" }
popd
Altere a primeira linha para corresponder ao seu caminho. (cole o trecho inteiro e pressione enter duas vezes)
Responder3
presumindo que todos os arquivos de entrada terminem com um espaço e pelo menos um dígito, esta parece ser mais uma maneira de fazer o trabalho. ele NÃO verifica números falsos, embora. [sorriso]
o que faz ...
- define os diretórios de origem e destino,
estou sempre preocupado em destruir os arquivos originais, então issocopia-osem vez derenomeando-os. se você quiser fazer isso diretamente, substituaCopy-Item
porRename-Item
. - cria alguns diretórios e arquivos de teste e
remove toda a região quando você estiver pronto para fazer as coisas de verdade. - define o tipo de arquivo a ser capturado
- obtém os arquivos que correspondem ao filtro
- remove quaisquer arquivos cujos
.BaseName
adereços NÃO terminem com espaço e pelo menos um dígito - divide os
.Basename
espaços e pega o último item nos resultados - adiciona o
.Extension
suporte ao acima - constrói onovonome completo do arquivo
- copia o nome completo do arquivo ANTIGO para o novo nome completo do arquivo
- o
-PassThru
naCopy-Item
linha envia informações de "criou um arquivo" para a tela
o código ...
$SourceDir = "$env:TEMP\InFiles"
$DestDir = "$env:TEMP\OutFiles"
#region >>> make some test dirs & files
$SourceDir, $DestDir |
ForEach-Object {
$Null = mkdir -Path $_ -ErrorAction 'SilentlyContinue'
}
# the last file is not to be worked on - wrong pattern
@'
FName LName 1234.txt
Alfa Bravo Charlie 89.txt
First Middle Last 666.txt
Wiki Tiki Exotica Music.txt
'@ -split [System.Environment]::NewLine |
ForEach-Object {
$Null = New-Item -Path $SourceDir -Name $_ -ItemType 'File' -ErrorAction 'SilentlyContinue'
}
#endregion >>> make some test files
$Filter = '*.txt'
Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File |
Where-Object {
# filter out any basename that does NOT end with a space followed by at least one digit
$_.BaseName -match ' \d{1,}$'
} |
ForEach-Object {
# split on the spaces & take the last item from the resulting array
$NewBaseName = $_.BaseName.Split(' ')[-1]
$NewFileName = '{0}{1}' -f $NewBaseName, $_.Extension
$FullNewFileName = Join-Path -Path $DestDir -ChildPath $NewFileName
Copy-Item -LiteralPath $_.FullName -Destination $FullNewFileName -PassThru
}
Responder4
Você pode fazer isso com um arquivo em lote usando o método a seguir.
Isso funcionará independentemente de quantas letras e espaços houver no início.
@echo off
setlocal enabledelayedexpansion
set "fPath=C:\test\my files\"
:: For each .txt file found in path %fPath% do....
for /F "tokens=*" %%a in ('DIR /B /ON "%fPath%*.txt"') do (
echo Processing: %%a
set "oName=%%a"
set "fName=%%a"
call :loop
)
echo Finished
endlocal
pause
:eof
exit /B
::=====================================================================
:: Check if the name is only numbers plus ".txt" on the end and if not, then remove the first character and check again.
:: If only numbers remaining, rename the original file. If no characters left then no match found and should go to next file.
:loop
if "!fName!"==".txt" exit /B
echo !fName!|findstr /r /c:"^[0-9]*\.txt$">nul
if !errorlevel! NEQ 0 set "fName=!fName:~1!" && goto :loop
ren "%fPath%%oName%" !fName!
exit /B