1

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

Compo
  • 36,585
  • 5
  • 27
  • 39
  • I updated the question, my bad for not making it clear in the first place. @Compo – Duy Hoang Nguyen Jan 01 '23 at 12:27
  • 1
    You want `obj_A`, which is `_`, but you extract `` instead. Besides that, you need [delayed expansion](https://stackoverflow.com/questions/30282784/variables-are-not-behaving-as-expected/30284028#30284028) – Stephan Jan 01 '23 at 12:43

1 Answers1

0

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"
Magoo
  • 77,302
  • 8
  • 62
  • 84
  • My God! It works like a charm! Thanks for your brilliant answer. I'd like to know more, if you don't mind. In which command do we assign the value for %%V and %%W? Because I can't see %%V and %%W defined anywhere before that (sorry if it's a stupid question, I'm just curious about the code" – Duy Hoang Nguyen Jan 02 '23 at 03:32
  • The token numbers listed in the `tokens=` option are assigned, lowest to the nominanated metavariable (`%%U`), next-lowest to the next alphabetically and so on. Token `*` means the remainder of the string after the highest token number allocated. The documentation is cleverly hidden but executing `for /?` from the prompt will reveal all..... – Magoo Jan 02 '23 at 04:23