A set of files have "Main Folder Name" (explicit) and a SubFolderName (hinted) in their filenames.
The intention is to just have them organized in new folders by "Main Folder Name" and SubFolderName then have all files moved to their corresponding new folders using batch script.
Example:
|>SourceDirectory
|>Main Folder Name (0001) S01E01 - FileDescription.bmp
|>Main Folder Name (0001) S01E01 - FileDescription.srt
|>Main Folder Name (0001) S01E02 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.srt
|>Main Folder Name (0007) S03E01 - FileDescription.jpg
|>Main Folder Name (0007) S03E02 - FileDescription.png
|>Main Folder Name (0007) S03E03 - FileDescription.srt
|>Main Folder Name (0012) S25E01 - FileDescription.ico
|>Main Folder Name (0012) S25E02 - FileDescription.txt
Intended Outcome
|>SourceDirectory
|>Main Folder Name (0001)
|>SubFolderName 1
|>Main Folder Name (0001) S01E01 - FileDescription.bmp
|>Main Folder Name (0001) S01E01 - FileDescription.srt
|>Main Folder Name (0001) S01E02 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.srt
|>Main Folder Name (0007)
|>SubFolderName 3
|>Main Folder Name (0007) S03E01 - FileDescription.jpg
|>Main Folder Name (0007) S03E02 - FileDescription.png
|>Main Folder Name (0007) S03E03 - FileDescription.srt
|>Main Folder Name (0012)
|>SubFolderName 25
|>Main Folder Name (0012) S25E01 - FileDescription.ico
|>Main Folder Name (0012) S25E02 - FileDescription.txt
Spent days trying and taking tips from other posts but my grasp in batch commands proved to be just too basic for this task.
Here's my working pseudo code:
1. Take first file
2. Search for the string pattern S??E?? to give away:
FolderName = All chars on the left of S??
SubFolderNumber = NumericValue of ?? in S??
3. MakeDir \FolderName\"SubFolderName " SubFolderNumber
4. Move the file to that new subfolder in step #3
5. Recurse and do steps 1-4 to each file until the end of the list
Step #2 may be too simple for the experts in this community but it is not keeping my hands from pulling my hair. :D
Would really appreciate help from anyone who could spare the time and let me keep the little hair I have left.
CodePudding user response:
Painfully came up with a ver1.0.
Not fool-proof yet but does the job for now. Kind of slow though. Needs some tuning up from a kind expert out there, maybe a far better approach or even an overhaul.
Your kind suggestions are very much welcome.
@ECHO OFF
SETLOCAL EnableDelayedExpansion
FOR %%a in (*) DO (
SET FileName=%%~na
CALL:findString FileName ") S" pos
SET /A pos=pos 1
SET /A pos2=pos 2
CALL SET "NewFolderName=%%FileName:~0,!pos!%%"
CALL SET "NewSubFolderNumber=%%FileName:~!pos2!,2%%"
SET /A NewSubFolderNumber=NewSubFolderNumber
SET NewSubFolder="%%~pa!NewFolderName!\SubFolderName !NewSubFolderNumber!\"
SET str="%%~fa" !NewSubFolder!
MD !NewSubFolder!
MOVE !str!
)
Seek and ye shall find. Found this missing link somewhere in the net just in time to save my remaining lock of hair. (Anyone knows why there isn't a built-in INSTR() function in the first place?)
:findString -- returns position of first occurrence of a string in another string, case sensitive, maximum string length is 1023 characters
:: -- %~1: in - varible name of a string to be searched
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
:credit belongs to
:$source http://www.dostips.com
:Posted By: DosItHelp
:Expert
:Posts: 239
:Joined: 18 Feb 2006 19:54
SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
set "s=!str:~%%a!"
if not defined pos if "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF
Hope this can help others.
CodePudding user response:
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following setting for the source directoryis a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"
FOR /L %%s IN (0,1,9) DO FOR /L %%t IN (0,1,9) DO IF EXIST "* S%%s%%tE*" (
FOR /L %%e IN (0,1,9) DO FOR /L %%f IN (0,1,9) DO IF EXIST "* S%%s%%tE%%e%%f -*" (
FOR /f "delims=" %%b IN ('dir /b /a-d "* S%%s%%tE%%e%%f -*"') DO (
SET "fullname=%%b"
FOR /f "tokens=1,2delims=:" %%q IN ("!fullname: S%%s%%tE%%e%%f =:!") DO (
IF %%s==0 (
rem MD "%%q\%%t" 2>nul
rem MOVE "%%b" "%%q\%%t\" >nul
ECHO MD "%%q\%%t"
ECHO MOVE "%%b" "%%q\%%t\"
) ELSE (
rem MD "%%q\%%s%%t" 2>nul
rem MOVE "%%b" "%%q\%%s%%t\" >nul
ECHO MD "%%q\%%s%%t"
ECHO MOVE "%%b" "%%q\%%s%%t\"
)
)
)
)
)
dir/s
popd
GOTO :EOF
This batch is designed to REPORT what it intends to do, and should be tested against a test directory before applying it to your live data.
When you are satisfied with the results, remove the rem
comment keyword from the two md
and move
lines to activate. The echo
lines may be removed if desired.
The dir/s
at the end simply shows the result.
The key here is the string S??E??
.
by using %%s
and %%t
each set to 0
..9
in turn, we can see whether a file named * S00E*
..* S99E*
exists. If such a file exists, repeat the recipe using %%e
and %%f
to find * S00E00 -*
..* S99E99 -*
.
Then grab a list of the filenames using /b
for names-only and /a-d
for no directorynames, matching the specific S??E?? string calculated, and assign to %%b
.
We need to analyse %%b
so need delayedexpansion
and transfer to a regular variable fullname
to do so.
Since the filename does not contain :
, simply replace the S??E??
detected by :
and use for/f
tokens and delims options to break the name at the S??E?? -> :
%%r
is set to the part after and %%q
to that before. %%r
is not used in this process.
Then it's a matter of establishing the subdirectory in %%q
and the sub-subdirectory in %%s
or %%s%%t
.
The 2>nul
suppresses the directory exists
messages created if a directory is re-created, and the >nul
on the move
command suppresses the 1 file(s) moved
message.