如何根据每个文件名中留给固定分隔符字符串的字符串将文件移动到文件夹?

How to move files to folders based on string left to a fixed separator string in each file name?

例如我有一个名为的文件夹:

FIRSTNAME LASTNAME

我有文件:

FIRSTNAME LASTNAME CHK#123
FIRSTNAME LASTNAME CHK#145

我想批量自动移动所有文件。我有另一个 post:

的代码
@echo off
setlocal enabledelayedexpansion
pushd "C:\Folders\"
for %%a in (*) do (
    set fldr=%%~na
    set fldr=!fldr:~0,4!
    md "!fldr!"
    move "%%a" "!fldr!"
)
popd
pause
exit

但如果文件超过四个字符,它会创建一个包含前四个字符的文件夹。

我想要做的是批处理文件评估文件名,在分隔符字符串  CHK# 处停止,然后根据文件名左侧的名字和姓氏将文件移动到文件夹 [=13] =].

将文件名拆分成多个部分的一种方法是使用 space 和 # 作为 delims
并检查第三个标记是否为 CHK

:: Q:\Test19\SO_55462032.cmd
@echo off  
setlocal enabledelayedexpansion 
pushd "C:\Folders\" 
for %%F in ("* * CHK#*") do for /f "tokens=1-4 delims=# " %%A in ("%%F") Do (   
    if "%%C"=="CHK" (
        if not Exist "%%A %%B" MD "%%A %%B"
        Move "%%F" "%%A %%B"
    ) else if "%%D"=="CHK" (
        if not Exist "%%A %%B %%C" MD "%%A %%B %%C"
        Move "%%F" "%%A %%B %%C"
    )

) 
popd 
pause 
exit /b

示例输出:

> SO_55462032.cmd
        1 Datei(en) verschoben.
Drücken Sie eine beliebige Taste . . .
> tree a:\ /F
├───FIRSTNAME LASTNAME
│       FIRSTNAME LASTNAME CHK#123
│       FIRSTNAME LASTNAME CHK#145
│
└───Firstname Middlename Lastname
        Firstname Middlename Lastname CHK#987

使用 RegEx 的 PowerShell 解决方案通过使用
获取 CHK# 前面的文件名部分 lookahead zerolength assertion

## Q:\Test19\SO_55462032.ps1

Pushd "C:\Folder"

Get-ChildItem *CHK#* -File | Where Name -match '^(.*)(?= CHK#)' | ForEach-Object {
   If(!(Test-Path $Matches[1])){New-Item -ItemType Directory -Name $Matches[1]}
   $_ | Move-Item -Destination $Matches[1]
}
PopD

示例输出:

> tree /F
├───FirstName
│       FirstName CHK#654
│
├───FIRSTNAME LASTNAME
│       FIRSTNAME LASTNAME CHK#123
│       FIRSTNAME LASTNAME CHK#145
│
├───Firstname Middlename Lastname
│       Firstname Middlename Lastname CHK#987
│
└───Title Firstname MiddleName Lastname
        Title Firsname MiddleName Lastname CHK#159

这是针对此任务的简单批处理文件解决方案:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%I in ("C:\Folders\* CHK#*") do call :ProcessFile "%%I"
endlocal
goto :EOF

:ProcessFile
set "FileName=%~nx1"
set "CheckSum=%FileName:* CHK#= CHK#%"
call set "FolderName=%%FileName:%CheckSum%=%%"
md "%~dp1%FolderName%" 2>nul
move /Y %1 "%~dp1%FolderName%"
goto :EOF

 CHK# 后的字符串不能有等号或一个或多个百分号。

子例程 ProcessFile 将字符串部分从第一次出现 CHK# 开始到文件名末尾分配给环境变量 CheckSum.

再使用一个字符串替换从文件名中删除校验和字符串以获得文件夹名称。此命令行由 Windows 命令处理器双重解析,因为命令 call 在第一次解析时用环境变量 CheckSum 的当前值替换 %CheckSum% 并替换两者 %% 只差一个 %。在第二次解析时,将处理剩余的 set "FolderName=%FileName: CHK#123=%",从而将第一个文件名示例的字符串 FIRSTNAME LASTNAME 分配给环境变量 FolderName。另见 How does the Windows Command Interpreter (CMD.EXE) parse scripts?

要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /? 另见
  • md /?
  • move /?
  • set /?
  • setlocal /?