trilobutt
trilobutt

Reputation: 13

How can I move specific files from multiple subfolders to their respective parent folder? (Windows batch)

I have the following file and folder structure (using real names):

Carabidae/Pterostichinae/FolderNameXXX/dor/StackXXX/files.tif

My problem is that I need to get one specific file, PM*.*, from the StackXXX folders into their respective /dor parent folders. The StackXXX folder can then be deleted.

There are hundreds of FolderName. Ideally I would like a batch file I can run from the Carabidae folder.

This needs to be a batch file because there will be new FolderNames added constantly.

After a lot of searching, I found a semi-working solution from this StackOverflow answer:

for /f "delims==" %%i in ('dir /a:d /b') do for /f "delims==" %%f in ('dir %%i /a:d /b') do (move "%%i\%%f\PM*.*" "%%i"&&rd "%%i\%%f" /s /q)

It moves the file and deletes the folder, just as I want. But the problem is that it only works when run from a FolderName folder, which defeats the time-saving purpose of the script. I don't know how to modify it to recurse into subfolders so I can run it from the top folder.

Thank you very much for any help!

Upvotes: 1

Views: 363

Answers (2)

Magoo
Magoo

Reputation: 79982

@ECHO OFF
SETLOCAL
SET "sourcedir=u:\Carabidae"
FOR /f "tokens=1*delims=" %%a IN (
 'dir /b /s /a-d "%sourcedir%\pm*.*" '
 ) DO IF EXIST "%%a" (
 FOR %%p IN ("%%~dpa..\.") DO IF /i "%%~nxp"=="dor" (
  ECHO %%a|FINDSTR /i "\\dor\\Stack" >NUL
  IF NOT ERRORLEVEL 1 (
   ECHO MOVE /y "%%~dpa\pm*.*" "%%~dpa..\"
   ECHO RD /s /q "%%~dpa"
  )
 )
)

GOTO :EOF

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

Find all of the pm*.* files, filenames to %%a

Ensure the parent directory is dor and ensure that \dor\stack\ is in the path. If so, move the file(s) and remove the directory.

The if exist gate ensure no hiccoughs if a target directory contains more than one pm*.* file.

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)

The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.

Add >nul at the end of the move command to suppress the move-report if required.

As usual, I'd suggest you test against a representative subtree first.

Upvotes: 2

aschipfl
aschipfl

Reputation: 34899

Here is a possible solution, given that only the XXX parts in your path sample are variable:

rem // Enumerate `FolderName*` directories:
for /D %%R in ("Carabidae\Pterostichinae\FolderName*") do (
    rem // Enumerate `Stack*` sub-directories within `dor` sub-directories:
    for /F "delims= eol=|" %%D in ('dir /B /A:D "%%~R\dor\Stack*"') do (
        rem // Check for `PM*.*` files in `Stack*` sub-directories:
        (
            rem // Enumerate `PM*.*` files:
            for /F "delims= eol=|" %%F in ('dir /B /A:-D "%%~R\dor\%%D\PM*.*"') do (
                rem /* Move `PM*.*` file one directory level up, overwriting
                rem    an already existing file, if applicable: */
                ECHO move /Y "%%~R\dor\%%D\%%F" "%%~R\dor\%%F"
            )
        ) && (
            rem /* Remove `Stack*` sub-directory after file movement;
            rem    this is skipped if no `PM*.*` files have been found in the `Stack*`
            rem    sub-directory, so when the `for /F %%F` loop did never iterate: */
            ECHO rd /S /Q "%%~R\dor\%%D"
        )
    )
)

After having successfully tested whether or not the correct items are returned, remove the upper-case ECHO commands to actually move PM*.* files and remove Stack* directories!

Upvotes: 1

Related Questions