Batch file to Move files based on part of filename

2019-10-18 11:09发布

问题:

Found a pyhton solution here, but I need a batch file-based solution.

Have many files:

  • SSP4325_blah-blah-blah.xml
  • JKP7645_blah.xml
  • YTG6457-blah-blah.xml

And folder names that contain a piece of the file name:

  • RefID - SSP4325, JKP7645, GHT1278, YRR0023
  • RefID - YTG6457

I'm looking for a batch solution which would read a portion of the file name at the front (before either the first dash or underscore) and then move that file into the folder where the front of the filename exists as part of the folder name.

So in the above examples, the first two files (SSP4325 and JKP7645) were moved into the first folder because it contained it contained that text as part of the folder name.

The third file would be moved into the second folder.

I have hundreds of files and 63 folders. So I'm hoping to be able to automate.

Can't use Powershell or Python due to limitations of the environment. So hoping for a batch file approach.

Thanks. Sean.

回答1:

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
 'dir /b /a-d "%sourcedir%\*.xml" '
 ) DO (
 FOR /f "tokens=1delims=_-" %%b IN ("%%a") DO (
  FOR /f "delims=" %%d IN (
  'dir /b /ad "%destdir%\*%%b*" '
  ) DO (
   ECHO(MOVE "%%a" "%destdir%\%%d\"
  )
 )
)

GOTO :EOF

You would need to change the settings of sourcedir and destdir to suit your circumstances.

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)

After establishing the directories, the outer loop puts the filename in %%a, the next loop gets the first part of that name, up to but not including the first - or _ (the delims specified) into %%b.

The inner loop finds the target directory containng %%b in the destination directory and constructs an appropriate move line.



回答2:

This solution review the folders just one time and store they in an array, so this method should run faster.

@echo off
setlocal EnableDelayedExpansion

rem Process the folders
set i=0
for /D %%a in (*) do (

   rem Store this folder in the next array element
   set /A i+=1
   set "folder[!i!]=%%a"

   rem Separate folder in parts and store the number of the array element in each one
   for %%b in (%%a) do set "part[%%b]=!i!"

)

rem Process the files
for %%a in (*.xml) do (

   rem Get the first part of name
   for /F "delims=-_" %%b in ("%%a") do (

      rem If such a folder exists...
      if defined part[%%b] (

         rem Get the number of the corresponding array element and move the file
         for %%n in (!part[%%b]!) do ECHO move "%%a" "!folder[%%n]!"

      ) else (

         echo No folder exists for this file: "%%a"

      )

   )
)

This method have also several advantages: you may check if a certain folder does not exists, or get the number of files moved to each folder, etc. If you are not interested in these points, just remove the if command and make the code simpler...

An explanation of array management in Batch files is given at this answer.