Как переименовать файлы - Удалить имя и сохранить номер

Как переименовать файлы - Удалить имя и сохранить номер

Мне нужно переименовать много файлов, содержащих имя и номер значка.

Файлы выглядят так: "John Doe 1234.txt" и мне нужно переименовать его в 1234.txt
(новый файл должен содержать только номер значка).
Также номер значка не фиксированный, он может содержать 3-4 цифры.

Обновление: Имя файла содержит 2-3 имени, разделенных пробелами. Например: "John Doe 123.txt" или "John Junior Doe 1234.txt"

Я думал удалить все буквы и пробелы из имени и оставить только цифры, но я недостаточно хорошо знаю Powershell.

Может кто-нибудь мне помочь?

решение1

Имена файловне могусодержат специальные символы ( /\:*?"<>|), но могут содержать символы типа %и !, которые могут вызвать cmd.exeнеправильный перехват, поэтому код не является защищенным от дурака. КОД ТЕПЕРЬ НАДЕЖЕН.

@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

Скриншот:


Примечание: может обрабатывать только до 31 файла из-заSETLOCAL МОЕ ПРЕДПОЛОЖЕНИЕ БЫЛО НЕВЕРНЫМ.Он может обрабатывать бесконечное количество файлов благодаря парным расширениям SETLOCALи ENDLOCAL.

решение2

Предположим, что все имена файлов имеют формат «Имя Фамилия Номер.txt»

Вы можете запустить:

pushd "C:\Temp\su\"
dir | ? { $_.Name -like "*.txt" } | 
% { Rename-Item $_ "$($_.BaseName.split(' ')[2])$($_.Extension)" }
popd

Измените первую строку так, чтобы она соответствовала вашему пути. (вставьте весь фрагмент и дважды нажмите Enter)

Скриншот, показывающий начальные имена файлов, команду, а затем результат.

решение3

Если предположить, что все входные файлы заканчиваются пробелом и затем по крайней мере одной цифрой, то это выглядит как еще один способ выполнить задачу. Однако он НЕ проверяет наличие дубликатов чисел. [ухмылка]

что оно делает ...

  • определяет исходный и целевой каталоги.
    Я всегда нервничаю из-за того, что могу испортить исходные файлы, поэтому этокопирует ихвместопереименовывая их. если вы хотите сделать это напрямую, замените Copy-Itemна Rename-Item.
  • создает несколько тестовых каталогов и файлов,
    удаляет всю эту область, когда вы готовы действовать по-настоящему.
  • определяет тип файла для захвата
  • получает файлы, соответствующие фильтру
  • удаляет все файлы, чьи .BaseNameсвойства НЕ заканчиваются пробелом и хотя бы одной цифрой
  • разбивает .Basenameна пробелы и берет последний элемент в результатах
  • добавляет .Extensionопору к вышесказанному
  • строитновыйполное имя файла
  • копирует СТАРОЕ полное имя файла в НОВОЕ полное имя файла
  • на -PassThruлинии Copy-Itemотправляет на экран информацию о создании файла

код ...

$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
        }

решение4

Это можно сделать с помощью пакетного файла, используя следующий метод.

Это будет работать независимо от того, сколько букв и пробелов в начале.

@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

Связанный контент