ファイル名を変更する方法 - 名前を削除して番号を残す

ファイル名を変更する方法 - 名前を削除して番号を残す

名前とバッジ番号が含まれる多数のファイルの名前を変更する必要があります。

ファイルは「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

すべてのファイル名が「First Last Number.txt」という形式であると仮定します。

以下を実行できます:

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

最初の行をパスに合わせて変更します。(スニペット全体を貼り付けて Enter キーを 2 回押します)

最初のファイル名、コマンド、結果を表示するスクリーンショット。

答え3

すべての入力ファイルがスペースで終わり、その後に少なくとも 1 つの数字が続くと仮定すると、これは同じ作業を実行するための別の方法のように見えます。ただし、重複した数字はチェックされません。[ニヤリ]

それは何をするのか...

  • ソースと宛先のディレクトリを定義します。
    私は元のファイルを上書きすることに常に神経質なので、これはコピーするの代わりに名前を変更する直接実行したい場合は、Copy-Itemを に置き換えますRename-Item
  • いくつかのテスト ディレクトリとファイルを作成し、
    実際に作業する準備ができたらその領域全体を削除します。
  • 取得するファイルの種類を定義します
  • フィルターに一致するファイルを取得します
  • .BaseNameプロパティがスペースと少なくとも1つの数字で終わらない ファイルを削除します。
  • スペースで分割し.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

関連情報