Search code examples
windowsbatch-filecmd

How do I create batch folder from part of file name, move files into folder with a modified name?


I have a list of files with the following filename

gml_Object_obj_A_Script_0.txt

gml_Object_obj_B_Script_1.txt

with obj_A, obj_B is the name of objects and Script_0, Script_1 is the file names

I need a Windows batch file to create folder based on object name, then move the files to each folder and rename it

In the example above, after using the batch file, I'll have 2 folders

Folder obj_A, contains file Script_0.txt

Folder obj_B, contains file Script_1.txt

So far I've come across a nice post here How do I create folder from file name and move files into folder?

But I'm not good with Windows Batch command, so I can't modify it to match my need

Here's my code (which is NOT WORKING)

    @echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=E:\TestBatch"
set "DestDir=E:\TestBatch"

for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%SourceDir%\gml_Object_obj_*" 2^>nul') do (
    for /F "eol=| tokens=2 delims=_" %%B in ("%%~nA") do (
        md "%DestDir%\%%B" 2>nul
        set "FileName=%%A"
        call move /Y "%SourceDir%\%%A" "%DestDir%\%%B\%%FileName:~3%%"
    )
)
endlocal

The result after running this code, is one folder called "Object" with 2 files

_Object_obj_A_Script_0.txt

_Object_obj_B_Script_1.txt


Solution

  • Analysing your code,

    %%A would contain a filename, eg. gml_Object_obj_A_Script_0.txt.

    %%B is set to the second _-delimited token of %%~nA, which is Object. (The ~n picks the name part of %%A,so is irrelevant here)

    The destination directory is established using %%B=Object

    filename is set to %%A=gml_Object_obj_A_Script_0.txt

    The move command is CALLed. This executes

        move /Y "E:\TestBatch\gml_Object_obj_A_Script_0.txt" "E:\TestBatch\Object\%FileName:~3%"
    

    Where filename is set to gml_Object_obj_A_Script_0.txt, so the move filename is gml_Object_obj_A_Script_0.txt except for the first 3 characters, hence _Object_obj_A_Script_0.txt

    It would appear that Stephan has missed the call keyword.

    So - that's why your code acted as it did.


    @ECHO Off
    SETLOCAL
    rem The following settings for the directories and filenames are names
    rem that I use for testing and deliberately includes spaces to make sure
    rem that the process works using such names. These will need to be changed to suit your situation.
    
    SET "sourcedir=u:\your files"
    SET "destdir=u:\your results"
    
    for /F "eol=| delims=" %%E in ('dir /B /A-D-H "%SourceDir%\gml_Object_obj_*" 2^>nul') do (
     for /F "eol=| tokens=3,4* delims=_" %%U in ("%%E") do (
      md "%DestDir%\%%U_%%V" 2>nul
      move /Y "%SourceDir%\%%E" "%DestDir%\%%U_%%V\%%W" >nul
     )
    )
    
    GOTO :EOF
    

    Always verify against a test directory before applying to real data.

    I prefer to avoid ADFNPSTXZ (in either case) as metavariables (loop-control variables) 
    ADFNPSTXZ are also metavariable-modifiers which can lead to difficult-to-find bugs 
    (See `for/f` from the prompt for documentation)
    

    My code: (I'll use YOUR directorynames)

    %%E would contain a filename, eg. gml_Object_obj_A_Script_0.txt.

    %%U is set to the third _-delimited token of %%A, which is obj, %%V to the fourth, A and %%W to the remainder, Script_0.txt.

    The destination directory is established using %%U_%%V=obj_A

    The move command is executed

        move /Y "E:\TestBatch\gml_Object_obj_A_Script_0.txt" "E:\TestBatch\obj_A\Script_0.txt"