Gergő
Gergő

Reputation: 13

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

For example I have a folder called:

FIRSTNAME LASTNAME

And I have the files:

FIRSTNAME LASTNAME CHK#123
FIRSTNAME LASTNAME CHK#145

I want to make a batch to move all files automatically. I have this code from another 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

But it creates a folder with the first four characters if the file has more than four characters.

What I want to do is that the batch file evaluates the file name, stops at separator string  CHK# and moves the file to the folder based on first and last name in file name left to  CHK#.

Upvotes: 1

Views: 464

Answers (3)

Mofi
Mofi

Reputation: 49097

Here is a simple batch file solution for this task:

@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

The string after  CHK# must not have an equal sign or one or more percent signs.

The subroutine ProcessFile assigns with a string substitution the string part beginning from first occurrence of CHK# to end of file name to environment variable CheckSum.

One more string substitution is used to remove the checksum string from file name to get the folder name. This command line is double parsed by Windows command processor because of command call to replace on first parsing %CheckSum% by current value of environment variable CheckSum and replace both %% by just a single %. On second parsing the remaining set "FolderName=%FileName: CHK#123=%" is processed resulting in assigning to environment variable FolderName the string FIRSTNAME LASTNAME for the first file name example. See also How does the Windows Command Interpreter (CMD.EXE) parse scripts?

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

Upvotes: 1

user6811411
user6811411

Reputation:

A PowerShell solution using a RegEx to get the file name parts in front of CHK# by using
a lookahead zerolength assertion

## Q:\Test\2019\04\01\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

Sample output:

> 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

Upvotes: 1

user6811411
user6811411

Reputation:

One way to split the file name into parts is to use the space and # as delims
and check if the 3rd token is CHK

:: Q:\Test\2019\04\01\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

Sample output:

> 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

Upvotes: 0

Related Questions