Felix Bernhard
Felix Bernhard

Reputation: 415

Windows Batch create folders based on file names

I want to create folders based on file names that look like this:

file with words 01.wav
file with words 02.wav
file with words 03.wav
file with more words 01.wav
file with more words 02.wav
...

the tree should look like this

Folder
|----file with words
     |----file with words 01.wav
     |----file with words 02.wav
     |----file with words 03.wav
|----file with more words
     |----file with more words 01.wav
     |----file with more words 02.wav

and the files within should keep their original name How can I address the last whitespace before each number? I can't specify a fixed value for "tokens" because the position of the last whitespace varies from file to file. This was my approach:

FOR /f "tokens=1*" %%a IN (
 'dir /b /a-d "* *.wav"'
 ) DO (
 ECHO MD %%a
 ECHO MOVE "%%a %%b" .\%%a\
)
PAUSE

-> ECHO to debug the result

Upvotes: 1

Views: 2165

Answers (3)

dbenham
dbenham

Reputation: 130819

Here is a version that uses JREPL.BAT - a hybrid JScript/batch utility that performs regular expression text replacements.

The advantages of this solution are that it only attempts to move .wav files whose name matches {baseName}{space}{digit}{digit}, and it will not move files if it cannot create the {baseName} folder because file {baseName} already exists. These features could be added to the pure batch solutions already posted. However, I find it easier to build a robust solution via JREPL.BAT.

@echo off
for /f "tokens=1,2 delims=:" %%A in (
  'dir /b "* ??.wmv" ^| jrepl "(.+?) +\d\d\.wmv$" "$1+':'+$0" /i /jmatch'
) do (
  if not exist "%%A\" if not exist "%%A" (
    md "%%A"
  ) else echo Can't create folder "%%A" because a file exists with that name
  if exist "%%A\" move "%%B" "%%A" >nul
)

Upvotes: 0

MC ND
MC ND

Reputation: 70923

@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%a in (*.wav) do (
        set "filename=%%~na"
        setlocal enabledelayedexpansion
        for %%b in ("::\!filename: =\!\..") do ( endlocal & set "filename=%%~pnxb" )
        setlocal enabledelayedexpansion
        for /f "tokens=*" %%b in ("!filename:\= !") do ( 
            endlocal 
            if not exist "%%b\" md "%%b"
            if exist "%%b*.wav" move /y "%%b *.wav" "%%b"
        )
    )

The idea behind the code is to iterate over the list of files and for each one, the spaces in it name are replaced with a backslash (file\with\words\01) so we can use the for replaceable parameters to query the "parent folder" of the last element (the name without the ending numbers) and later replace the backslashes with spaces to get the final folder name.

The multiple setlocal/endlocal are included to handle the case of filenames that could include exclamation points (a problematic character when delayed expansion is enabled).

The code tries to move all matching files in each set with only one move command, but depending on the real names, it is possible that files from other set could also match. To avoid it, the line

if exist "%%b*.wav" move /y "%%b *.wav" "%%b"

should be converted into

 move /y "%%a" "%%b\"

so files are moved one by one without problems.

Upvotes: 2

Magoo
Magoo

Reputation: 80023

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
PUSHD "%sourcedir%"
FOR /f "delims=" %%a IN (
  'dir /b /a-d *.wav '
  ) DO (
 SET "filename=%%a"
 SET "dirname=%%a"
 CALL :genmove
)
popd

GOTO :EOF

:genmove
IF "%dirname:~-1%" neq " " set "dirname=%dirname:~0,-1%"&goto genmove
set "dirname=%dirname:~0,-1%"
ECHO(MD "%dirname%"
ECHO(MOVE "%filename%" ".\%dirname%\"
GOTO :eof

You would need to change the setting of sourcedir to suit your circumstances.

The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)

The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)

Simply generate the same name for the file and directory, trim off the last character from the name until that character is a space, trim that off and you have the required dirname and filename.

Upvotes: 0

Related Questions