Como renomear arquivos – Remova o nome e mantenha o número

Como renomear arquivos – Remova o nome e mantenha o número

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 ( /\:*?"<>|), mas pode conter caracteres como %e !que podem causar cmd.exeinterceptação incorreta, portanto o código não é infalível. O CÓDIGO AGORA É 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

Captura de tela:


Observação: só pode lidar com até 31 arquivos, devido aoSETLOCAL MINHA ASSUNÇÃO ESTAVA ERRADA.Ele pode lidar com arquivos infinitos, por causa dos SETLOCALarquivos 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)

Captura de tela para mostrar os nomes dos arquivos iniciais, o comando e depois o resultado.

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, substitua Copy-Itempor Rename-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 .BaseNameadereços NÃO terminem com espaço e pelo menos um dígito
  • divide os .Basenameespaços e pega o último item nos resultados
  • adiciona o .Extensionsuporte ao acima
  • constrói onovonome completo do arquivo
  • copia o nome completo do arquivo ANTIGO para o novo nome completo do arquivo
  • o -PassThruna Copy-Itemlinha 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

informação relacionada