Arthor
Arthor

Reputation: 674

Batch Script to create folder based on name, add to existing code

The code below works fine, here is a list of it's functions:

  1. It moves files based on the fist 4 characters to a pre-created folder with the same first 4 characters
  2. If the folder does not exist, it will not move the file, as there is no folder with the same fist 4 chars.

    @echo on
    setlocal enabledelayedexpansion
    cls
    
    pushd R:\Contracts\Sites
    
    for /f "tokens=*" %%1 in ('dir /a-d /b *') do (
        set filename=%%1&set dirname=!filename:~0,4!
    
        for /f "tokens=*" %%A in ('dir /ad /b') do (
             set dirid=%%A & set dirid=!dirid:~0,4!
    
             if "!dirid!" equ "!dirname!" move %%1 %%A
        )        
    )
    

I would like to add one extra function to this code please. Pleas have a look at the example below.

I have 5 files

I would like the code to CREATE a folder if it does not exist, based on the file name if it has the extension docx or pptx.

So with the above example it would create a folder named: "X32A-test". Then all the other files with "X32A" in the front of the name will be moved to that newly created folder "X32A-test".

I hope it is clear enough. If not please ask me for more information.

Thank you

Upvotes: 1

Views: 1405

Answers (3)

Andriy M
Andriy M

Reputation: 77737

I can see the entire process (including the part already implemented) like this:

  1. All the files that are not yet in their "home" directories are moved there.

  2. For all .docx and .pptx files left, create directories based on the files' names.

  3. Obviously, the step #2 creates new "homes" and those will still be "uninhabited" this far. So all that is left to do now is to repeat the step #1.

So I would probably reorganised your process and, with the additional requirement, it could be implemented this way:

…

PUSHD your_root_directory

FOR /D %%D IN (*) DO (
  CALL :movefiles "%%D"
)

FOR %%F in (*.docx *.pptx) DO (
  MKDIR "%%~dpnF"
  CALL :movefiles "%%~dpnF"
)

…

GOTO :EOF

:movefiles
SET "dirname=%~n1"
SET "mask=%dirname:~0,4%*"
MOVE "%~dp1%mask%" %1

Note: The steps #2 and #3 could be either implemented as separate loops or combined in one. The above script uses the latter approach.

Upvotes: 1

dbenham
dbenham

Reputation: 130919

It is much simpler and more efficient to use the simple FOR instead of FOR /F in your case.

And rather than looping through every file and moving them individually, it is easier and more efficient to use wildcards.

The first loop finds the .pptx and .docx files and creates folders as needed

The second loop finds all the directories and moves all files that start with the directory name into the directory.

@echo on
setlocal enableDelayedExpansion
cls

pushd R:\Contracts\Sites

for %%F in (*.docx *.pptx) do (
  set "folder=%%F"
  2>nul md !folder:~0,4!
)
for /d %%F in (*) do move %%F* %%F
popd

If needed, you can protect yourself against directory names shorter than length 4.

@echo on
setlocal enableDelayedExpansion
cls

pushd R:\Contracts\Sites

for %%F in (*.docx *.pptx) do (
  set "folder=%%F"
  set folder=!folder:~0,4!
  if !folder:~0,3! neq !folder! 2>nul md !folder!
)
for /d %%F in (????) do (
  set "folder=%%F"
  if "!folder:~0,3!" neq "%%F" move %%F* %%F
)
popd

Note that this solution may fail if a file name contains !. If that arises then you need to toggle delayed expansion on and off within the loop(s).

Upvotes: 2

paxdiablo
paxdiablo

Reputation: 882716

You can use negative offsets in the !var:~offset,len! evaluation as follows:

set fspec=X32A-test.docx
echo !fspec:~-10!
echo !fspec:~0,-10!

That second line above gives you -test.docx and you can simply check that against your two desired possibilities with an if statement (or two).

Then you can use the third line to get the rest of the name for creating a directory.

The following example script shows how this could be done:

@setlocal enableextensions enabledelayedexpansion
@echo off
set fspec=X32A-test.docx
set bit1=!fspec:~-10!
set bit2=!fspec:~0,-10!
if .!bit1!.==.-test.docx. echo mkdir !bit2!
if .!bit1!.==.-test.pptx. echo mkdir !bit2!
endlocal

I'm echoing the mkdir command rather than executing it so you need to take out the echo. You'll also need to integrate the set and if statements into your loop but, based on what you have so far, you should have little trouble with that.


If, as you seem to indicate in a comment, the first four characters are the key and the last five decide on whether to make the directory, as in:

x32s-test.docx
a21w-production.pptx
xxxx-whatever_the_blazes_you_want.some_other_rubbish.docx

Then you're really only interested in the first four and last five:

@setlocal enableextensions enabledelayedexpansion
@echo off
set fspec=a12b-whatever_the_blazes_you_want.some_other_rubbish.docx
set bit1=!fspec:~-5!
set bit2=!fspec:~0,4!
if .!bit1!.==..docx. echo mkdir !bit2!
if .!bit1!.==..pptx. echo mkdir !bit2!
endlocal

This checks the correct extensions and outputs:

mkdir a12b

as expected.

Upvotes: 1

Related Questions