Search code examples
batch-filecmddirectory

How to organize files in folders?


I have this script that currently works partially.

Step 1 (working):
More precisely, it groups all my .mp4 files found in the directory. I choose the number of .mp4 files in each folder. So far all good.

Step 2 (not working):
When I try to move the folders created together with the MP4 files inside and group them by 15 or as many as I need, I can't find the optimal solution.

@echo off
setlocal enabledelayedexpansion
PushD %~dp0
set "filesInfolder=60"
set "foldersInfolders=15"
set "fcount=0"
set "fcounta=0"
set idx=0
set idxa=0

REM here all the .mp4 files will be grouped 60 in each folder

for /F "delims=" %%I in ('dir /a-d /o:n /b *.mp4') do (
    REM echo Processing %%I
    set /a idx=idx %% filesinfolder +1
    if !idx! equ 1 set /a fcount+=1
    md Videos-!fcount! 2>nul
    move "%%I" "Videos-!fcount!\"
) 

REM here I need the folders created together with the .mp4 files to be grouped by 15 in other folders.

for /D "delims=" %%A in (*.*) do  (
    REM echo Processing %%A
    set /Y idxa=idxa %% foldersinfolders +1
    if !idxa! equ 1 set /a fcounta+=1
    md Canal-!fcounta! 2>nul
    move "%%~fA" "Canal-!fcounta!\"
)

Everything happens in a loop until all the .mp4 files are moved.


Solution

  • There could be used the following batch file to organize the video files in directory of the batch file by moving them to dynamically created directories as long as no MP4 file contains an exclamation mark in file name.

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    pushd "%~dp0"
    if not exist "*!*.mp4" goto MoveFiles
    echo ERROR: Moving video files not possible because of file names with ! in name.
    echo(
    echo Please rename first the following files(s):
    echo(
    dir *!*.mp4 /A-D /B
    echo(
    pause
    goto EndBatch
    
    :MoveFiles
    setlocal EnableDelayedExpansion
    set "FilesInFolder=60"
    set "FoldersInFolders=15"
    set "FileCount=%FilesInFolder%"
    set "CanalIndex=0"
    set "VideosIndex=%FoldersInFolders%
    for /F "eol=| delims=" %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do (
        if !FileCount! == %FilesInFolder% (
            set FileCount=0
            if !VideosIndex! == %FoldersInFolders% (
                set /A CanalIndex+=1
                set VideosIndex=1
            ) else set /A VideosIndex+=1
            set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
            md "!TargetFolder!" 2>nul
        )
        move /Y "%%I" "!TargetFolder!\" >nul
        set /A FileCount+=1
    )
    endlocal
    
    :EndBatch
    popd
    endlocal
    

    The environment variable TargetFolder with the two dynamic changed numbers CanalIndex and VideosIndex can be further modified to the wanted format.

    Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

    Please note that the ordering of the MP4 files by name caused by option /ON by command DIR is strictly alphabetic and not natural alphanumeric. The command line executed by FOR by starting one more cmd.exe in background with option /c and the command line appended as argument string(s) could be modified to get MP4 file names output and so processed next in a different order.

    Example of the FOR command line with moving MP4 files with the file names file (1).mp4, ... file (9).mp4, file (10).mp4, ... file (99).mp4, file (100).mp4, ... file (999).mp4, file (1000).mp4, ... file (9999).mp4:

    for /F "eol=| delims=" %%I in ('dir *.mp4 /A-D /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "([0-9])\.mp4$" ^& dir *.mp4 /A-D /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "([0-9][0-9])\.mp4$" ^& dir *.mp4 /A-D /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "([0-9][0-9][0-9])\.mp4$" ^& dir *.mp4 /A-D /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "([0-9][0-9][0-9][0-9])\.mp4$"') do (
    

    Please note that [0-9] matches also the characters ¹²³ which should be no problem here.

    To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

    • dir /?
    • echo /?
    • endlocal /?
    • findstr /?
    • for /?
    • goto /?
    • if /?
    • md /?
    • move /?
    • pause /?
    • popd /?
    • pushd /?
    • set /?
    • setlocal /?

    Extended version to process MP4 files in multiple directories specified in the first FOR loop instead of the batch file directory:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "FilesInFolder=60"
    set "FoldersInFolders=15"
    for %%# in ("%USERPROFILE%\Videos" "D:\Videos" "F:\Temp\Videos" "\\MyNAS\Videos") do (
        pushd %%# 2>nul
        if not errorlevel 1 (
            if not exist "*!*.mp4" (
                setlocal EnableDelayedExpansion
                set "FileCount=%FilesInFolder%"
                set "CanalIndex=0"
                set "VideosIndex=%FoldersInFolders%
                for /F "eol=| delims=" %%I in ('dir *.mp4 /A-D /B /ON 2^>nul') do (
                    if !FileCount! == %FilesInFolder% (
                        set FileCount=0
                        if !VideosIndex! == %FoldersInFolders% (
                            set /A CanalIndex+=1
                            set VideosIndex=1
                        ) else set /A VideosIndex+=1
                        set "TargetFolder=Canal-!CanalIndex!\Videos-!VideosIndex!"
                        md "!TargetFolder!" 2>nul
                    )
                    move /Y "%%I" "!TargetFolder!\" >nul
                    set /A FileCount+=1
                )
                endlocal
            ) else (
                echo(
                echo ERROR: Moving video files not possible because of file names with ! in name.
                echo(
                echo Please rename first the following files(s^) in: %%#
                echo(
                dir *!*.mp4 /A-D /B
                echo(
                pause
            )
            popd
        ) else (
            echo(
            echo ERROR: Failed to change to directory: %%#
            echo(
            pause
        )
    )
    endlocal