简体   繁体   中英

Move files into a subfolder of a destination directory

I started using batch commands last week and I've reached a real obstacle with a script I made.

What I want to do

Move a PDF file from C:\\Users\\JK\\Documents\\reports PDFs into pre-made subfolders in the destination W:\\Departments\\QA\\cases .

For example the script would move 2223 report.pdf to W:\\Departments\\QA\\cases\\2201 - 2300\\2223

What I tried

I made a script based off the answer in this thread

cls
@pushd %~dp0

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=C:\Users\JK\Documents\reports PDFs"
set "DestDir=W:\Departments\QA\cases\"

for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%SourceDir%\*.pdf" 2^>nul') do (
    for /F "eol=| tokens=1" %%B in ("%%~nA") do (
        for /D %%C in ("%DestDir%\%%B*") do move /Y "%SourceDir%\%%A" "%%C\"
    )
)

endlocal
popd

pause

Where I am stuck

How could I add subfolders or account for them in the destination directory?

FYI, I also tried adding a wildcard symbol at the end of the destination directory by changing %DestDir%\\%%B to %DestDir%\\*\\%%B* .

I would probably accomplish the task with the following script (see all the explanatory rem remarks):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_SOURCE=C:\Users\JK\Documents\reports PDFs" & rem // (source directory; `.` or `` is current, `%~dp0.` is script parent)
set "_TARGET=W:\Departments\QA\cases" & rem // (target directory; `.` or `` is current, `%~dp0.` is script parent)
set "_SUBDIR=#"      & rem // (set to non-blank value in order to create individual sub-directories)
set "_FMASK=????*.pdf"    & rem // (pattern to match source files)
set "_DMASK=???? - ????*" & rem // (pattern to match target directories)
set "_FFIL1=^[0123456789][0123456789][0123456789][0123456789] .*\.pdf$" & rem // (filter 1 for source files)
set "_FFIL2=^[0123456789][0123456789][0123456789][0123456789]\.pdf$"    & rem // (filter 2 for source files)
set "_DFIL1=^[0123456789][0123456789][0123456789][0123456789] - [0123456789][0123456789][0123456789][0123456789] .*$"
set "_DFIL2=^[0123456789][0123456789][0123456789][0123456789] - [0123456789][0123456789][0123456789][0123456789]$"

rem // Change into source directory:
pushd "%_SOURCE%" && (
    rem // Iterate through all files matching the specified pattern and filters:
    for /F "eol=| delims=" %%F in ('
        dir /B /A:-D-H-S "%_FMASK%" ^| findstr /I /R /C:"%_FFIL1%" /C:"%_FFIL2%"
    ') do (
        rem // Store full path of currently iterated file:
        set "FILE=%%~fF"
        rem // Extract the leading numeric part of the file name:
        for /F "eol=| delims= " %%N in ("%%~nF") do (
            rem // Store the numeric part:
            set "NUM=%%N"
            rem /* Remove any leading zeros from the numeric part of the file name, because
            rem    such cause the number to be unintentionally interpreted as octal: */
            set /A "INT=0" & for /F "eol=| tokens=* delims=0" %%Z in ("%%N") do 2> nul set /A "INT=%%Z"
        )
        rem // Change into target directory:
        pushd "%_TARGET%" && (
            rem // Iterate through all directories matching the specified pattern and filters:
            for /F "eol=| delims=" %%D in ('
                cmd /V /C 2^> nul dir /B /A:D-H-S "!_DMASK:|=%%I!" ^| findstr /I /R /C:"%_DFIL1%" /C:"%_DFIL2%"
            ') do (
                rem // Store name of currently iterated directory:
                set "TDIR=%%D"
                rem // Extract first (from) and second (to) numeric parts of directory names:
                for /F "eol=| tokens=1-2 delims=- " %%S in ("%%D") do (
                    rem // Remove any leading zeros from first (from) numeric part:
                    set /A "FRM=0" & for /F "eol=| tokens=* delims=0" %%Z in ("%%S") do set /A "FRM=%%Z"
                    rem // Remove any leading zeros from second (to) numeric part:
                    set /A "TOO=0" & for /F "eol=| tokens=* delims=0" %%Z in ("%%T") do set /A "TOO=%%Z"
                )
                rem // Toggle delayed variable expansion to avoid trouble with `!`:
                setlocal EnableDelayedExpansion
                rem /* Do integer comparisons to check whether the numeric part of the file name
                rem    lies within the range given by the directory name (from/to): */
                if !INT! geq !FRM! if !INT! leq !TOO! (
                    rem // Numeric part of file name lies within range, hence try to move file:
                    if defined _SUBDIR (
                        2> nul md "!TDIR!\!NUM!"
                        ECHO move "!FILE!" "!TDIR!\!NUM!\"
                    ) else (
                        ECHO move "!FILE!" "!TDIR!\"
                    )
                )
                endlocal
            )
            rem // Return from target directory:
            popd
        )
    )
    rem // Return from source directory:
    popd
)

endlocal
exit /B

You may need to adapt a few constants to your situation in the section commented with Define constants here: at the top.

After having tested the script for the correct output, remove the upper-case ECHO commands in front of the move commands! In order to avoid multiple 1 file(s) moved. messages, replace these ECHO commands by > nul .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM