Reputation: 13
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
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.
call /?
echo /?
endlocal /?
for /?
goto /?
and see also Where does GOTO :EOF return to?md /?
move /?
set /?
setlocal /?
Upvotes: 1
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
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