-1

I have been trying to create a batch file that I can just drop into the MAIN FOLDER dir and running it will move all of the *.EXT up one level into the Folder2 and Folder3 respectively:

C:\Main Folder\Folder2\Folder3a\File1.EXT
C:\Main Folder\Folder2\Folder3b\File2.EXT
C:\Main Folder\Folder2\Folder3c\File3.EXT
C:\Main Folder\Folder2\Folder3d\File1.EXT
C:\Main Folder\Folder3\Folder3a\File1.EXT
C:\Main Folder\Folder3\Folder3b\File2.EXT
C:\Main Folder\Folder3\Folder3c\File3.EXT
C:\Main Folder\Folder3\Folder3d\File1.EXT

The problem is that there are duplicates: File1.EXT in both Folder2 and Folder3 subfolders.
Everything I've found on here to move the files up one level always overwrites the duplicates.
And the solutions I've found for renaming duplicates didn't "merge" with the solutions for moving files.

Can anyone suggest an easier way?

  • 1
    This site is for helping you with your code, you've posted no code and therefore we have nothing to help you with. [Edit your question](https://stackoverflow.com/posts/49721863/edit) and include the batch file code you have tried and are having problems with. If you don't know how to do something then it is your job to search and try before coming here for help; you can use the search bar at the top of this page to look for key words. If you include `[batch-file]` at the beginning of the search bar, you should be able to narrow down results to that particular scripting language. – Compo Apr 08 '18 at 19:32
  • I refer you to your previous, [almost identical question](https://stackoverflow.com/q/49369626/6738015), and my response to it! – Compo Apr 08 '18 at 19:40
  • Rename _before_ moving. – SomethingDark Apr 08 '18 at 22:41
  • Possible duplicate of [How to create batch file that move files from sub-folder up one level renaming duplicates?](https://stackoverflow.com/questions/49369626/how-to-create-batch-file-that-move-files-from-sub-folder-up-one-level-renaming-d) – jwdonahue Apr 09 '18 at 00:25

2 Answers2

0
@echo off
setlocal

if "%~1" == "test" call :test

for /d /r %%F in (*) do (
    for /d %%G in ("%%F\*") do (
        for %%H in ("%%~G\*.EXT") do (
            call :move "%%~H" "%%~F"
        )
    )
)
exit /b

:move
setlocal

if /i not exist "%~2\%~nx1" (
    echo 1. move "%~1" "%~2"
    move "%~1" "%~2"
    exit /b
)

set "name=%~n1"

for /l %%I in (1 1 9) do (
    if "%name:~-4%" == " (%%I)" (
        set "name=%name:~0,-4%"
    )
)

for /l %%I in (1 1 9) do (
    if not exist "%~2\%name% (%%I)%~x1" (
        echo 2. move "%~1" "%~2\%name% (%%I)%~x1"
        move "%~1" "%~2\%name% (%%I)%~x1"
        exit /b
    )
)
exit /b

:test
if exist "Main Folder" rd /s /q "Main Folder"
call :prep "Main Folder\Folder2\Folder3a" "File1.EXT"
call :prep "Main Folder\Folder2\Folder3b" "File2.EXT"
call :prep "Main Folder\Folder2\Folder3c" "File3.EXT"
call :prep "Main Folder\Folder2\Folder3d" "File1.EXT"
call :prep "Main Folder\Folder3\Folder3a" "File1.EXT"
call :prep "Main Folder\Folder3\Folder3b" "File2.EXT"
call :prep "Main Folder\Folder3\Folder3c" "File3.EXT"
call :prep "Main Folder\Folder3\Folder3d" "File1.EXT"
pushd "Main Folder" || exit /b 1
echo Prepared to test.
pause
exit /b

:prep
if /i not exist "%~1" md "%~1"
if /i not exist "%~1\%~2" type nul > "%~1\%~2"
exit /b

Test code intregrated makes it easier to test. Remove the test code if desired. Test using test as 1st argument i.e. main.cmd test.

Based from loop you posted in How to create batch file that move files from sub-folder up one level renaming duplicates? The loop gets you target file path and destination directory path.

The label :move is called with each cycle of the loop and 1st determines if the destination file not exist. If not exist, does the move and exits the label. If does exist, uses another loop to detect and trims the filename if it ends with (N) where N is a number between 1 and 9. Then it enters another loop to move with a destination filename with 1st available (N) appended to the name.

Tested in root of D:\. The output I get is:

D:\> main.cmd test
Prepared to test.
Press any key to continue . . .
1. move "D:\Main Folder\Folder2\Folder3a\File1.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
1. move "D:\Main Folder\Folder2\Folder3b\File2.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
1. move "D:\Main Folder\Folder2\Folder3c\File3.EXT" "D:\Main Folder\Folder2"
        1 file(s) moved.
2. move "D:\Main Folder\Folder2\Folder3d\File1.EXT" "D:\Main Folder\Folder2\File1 (1).EXT"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3a\File1.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3b\File2.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
1. move "D:\Main Folder\Folder3\Folder3c\File3.EXT" "D:\Main Folder\Folder3"
        1 file(s) moved.
2. move "D:\Main Folder\Folder3\Folder3d\File1.EXT" "D:\Main Folder\Folder3\File1 (1).EXT"
        1 file(s) moved.

As it shows, 2 files are moved with (1) appended to the filename. That is the lines starting with 2.. Lines starting with 1. have moved with unmodified filenames.

michael_heath
  • 5,262
  • 2
  • 12
  • 22
0

This commented batch file can be used for this task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Search for any file two directory levels below specified directory
rem and pass to subroutine MoveFile the name of the file with full path.

for /D %%A in ("C:\Main Folder\*") do (
    for /D %%B in ("%%A\*") do (
       for /F "delims=" %%I in ('dir "%%B\*" /A-D /B /S 2^>nul') do call :MoveFile "%%I"
    )
)

endlocal
goto :EOF

:MoveFile
set "FilePath=%~dp1"
set "FileNameOnly=%~n1"
set "FileNameFull=%~1"
set "FileName+Ext=%~nx1"
set "FileExtension=%~x1"

rem For files staring with a dot and not containing one more dot.
if "%FileNameOnly%" == "" set "FileNameOnly=%~x1" & set "FileExtension="

rem Get path to parent folder ending with a backslash.
for /F "delims=" %%J in ("%FilePath:~0,-1%") do set "FileParent=%%~dpJ"

rem Uncomment the line below to see the values of the six File* variables.
rem set File & echo/

rem Does a file with current file name not exist in parent folder?
if not exist "%FileParent%%FileName+Ext%" (
    rem Move the file to parent folder and if this was successful
    rem delete the folder of the moved file if being empty now.
    move "%FileNameFull%" "%FileParent%%FileName+Ext%" >nul
    if not errorlevel 1 rd "%FilePath%" 2>nul
    goto :EOF
)

set "FileNumber=1"
:NextFile
if exist "%FileParent%%FileNameOnly%_%FileNumber%%FileExtension%" set /A "FileNumber+=1" & goto NextFile

move "%FileNameFull%" "%FileParent%%FileNameOnly%_%FileNumber%%FileExtension%" >nul
if not errorlevel 1 rd "%FilePath%" 2>nul
goto :EOF

The result for given example is:

C:\Main Folder\Folder2\File1.EXT
C:\Main Folder\Folder2\File1_1.EXT
C:\Main Folder\Folder2\File2.EXT
C:\Main Folder\Folder2\File3.EXT
C:\Main Folder\Folder3\File1.EXT
C:\Main Folder\Folder3\File1_1.EXT
C:\Main Folder\Folder3\File2.EXT
C:\Main Folder\Folder3\File3.EXT

And running the batch file a second time does not change anything.

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

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • rd /?
  • rem /?
  • set /?
  • setlocal /?

See also:

Mofi
  • 46,139
  • 17
  • 80
  • 143