Page 1 of 1

Bat: Move/MD/Find Carrying Multiple Variables from Txt File

Posted: 23 Nov 2009 05:30
by Boggie1688
Hi,

I'm really new to batch commands so bare with me.

I have a server that I downloads multiple directories to one directory. I want to create a batch file search the directory using a given set of directory names. I'd like to call this bat, search.bat.

Next I need to sort the files found in each directory. For example files ending in S01 need to go to a folder named S01. Files ending in S02 need to go to a folder named S02. I'll call this bat, sort.bat.

But before I can sort the files into the folders, I need to verify that there is a folder that corresponds to the file type. For example, if search.bat in conjunction with sort.bat found a directory named ABC with file S01, then I need verify.bat to make sure there is a corresponding ACB/S01 directory in directory hard drive.

If the directory is there then move.bat will move the file over. If the directory is not there, then verify.bat will create the directory on the other hard drive. Then move.bat will move the file there.

Its really complicated. Here is a example of the directory system:

C:Unsorted\ABC\S\S01.txt
C:Unsorted\DEG\S\S02.txt

These need to get moved to:

C:Sorted\ABC\S01.txt
C:Sorted\DEG\S02.txt

I know how to work the MD, Find, and Move commands. What is killing me is how to take a txt file and turn it into variables. Then having the find command search for the variables.

For example search.txt used by search.bat contains:
S01
S02

dir /s /b /ab C:Unsorted > results.txt
find search.txt <results.txt>null
if not errorlevel 1 call verify.bat &variable&

I know entering search.txt doesn't work, but I dunno how to get a it to find for each value inside of search.txt then use that variable in verify.bat

Inside of verify.bat that variable needs to be used again in another search command.

Can anyone help me?

Re: Bat: Move/MD/Find Carrying Multiple Variables from Txt F

Posted: 23 Nov 2009 11:59
by avery_larry
Boggie1688 wrote:Hi,

I'm really new to batch commands so bare with me.

I have a server that I downloads multiple directories to one directory. I want to create a batch file search the directory using a given set of directory names. I'd like to call this bat, search.bat.

Next I need to sort the files found in each directory. For example files ending in S01 need to go to a folder named S01. Files ending in S02 need to go to a folder named S02. I'll call this bat, sort.bat.

But before I can sort the files into the folders, I need to verify that there is a folder that corresponds to the file type. For example, if search.bat in conjunction with sort.bat found a directory named ABC with file S01, then I need verify.bat to make sure there is a corresponding ACB/S01 directory in directory hard drive.
I wouldn't bother with the verify. Just try to MD the directory, and if it already exists, it'll just fail.

If the directory is there then move.bat will move the file over. If the directory is not there, then verify.bat will create the directory on the other hard drive. Then move.bat will move the file there.

Its really complicated. Here is a example of the directory system:

C:Unsorted\ABC\S\S01.txt
C:Unsorted\DEG\S\S02.txt

These need to get moved to:

C:Sorted\ABC\S01.txt
C:Sorted\DEG\S02.txt

I know how to work the MD, Find, and Move commands. What is killing me is how to take a txt file and turn it into variables. Then having the find command search for the variables.
Use a for loop and a call to a label to grab each file, extract it's extension, MD the directory, and move the file.

For example search.txt used by search.bat contains:
S01
S02

dir /s /b /ab C:Unsorted > results.txt
find search.txt <results.txt>null
if not errorlevel 1 call verify.bat &variable&

I know entering search.txt doesn't work, but I dunno how to get a it to find for each value inside of search.txt then use that variable in verify.bat

Inside of verify.bat that variable needs to be used again in another search command.

Can anyone help me?


Something like this:

Code: Select all

@echo off
set "sourcedir=c:\unsorted"
set "destdir=c:\sorted"


for /f %%a in (search.txt) do (
   for /f %%b in ('dir /s /b /a-d "%sourcedir%\*.%%a"') do call :process "%%b"
)
echo All done.
goto :eof


:process
set "ext=%~x1"
set "ext=%ext:~1,99%"
md "%destdir%\%ext%" >nul 2>nul
move "%~1" "%destdir%\%ext%"
goto :eof

Posted: 23 Nov 2009 12:13
by Boggie1688
Wow thanks for the reply.

Ok I just want to go over your code so I can understand it well enough to work on it. I would really appreciate it.


for /f %%a in (search.txt) do (
for /f %%b in ('dir /s /b /a-d "%sourcedir%\*.%%a"') do call :process "%%b"
)

Is %%a a variable for each line of text? Hence its creating another variable %%b for C:\Unsorted\%%a?

It says if there is a directory C:\Unsorted\%%a then run process and pass the variable %%b.

Process is where I get lost.
Why are there two sets? What do both of them do?
What does >nul 2>nul do for md?
What does "%~1" stand for?

And lastly :eof? Points too?

Posted: 23 Nov 2009 12:39
by Boggie1688
Err.. I messed up my explanation of the destination directory.

I'm looking to do

C:Unsorted/House/S01E02.mkv
C:Unsorted/House/S02E02.mkv
C:Unsorted/Stargate/S01E02.mkv
C:Unsorted/Stargate/S01E01.mkv
to
C:Sorted/House/Season 1/S01E02.mkv
C:Sorted/House/Season 2/S02E02.mkv
C:Sorted/Stargate/Season 1/S02E02.mkv
C:Sorted/Stargate/Season 2/S01E02.mkv

Will this fix that?

@echo off
set "sourcedir=H:\Test\unsorted"
set "destdir=H:\Test\tv_shows"


for /f %%a in (tv.txt) do (
for /f %%b in ('dir /s /b "%sourcedir%\*%%a*.txt"') do call :process "%%b" "%%a"
)
)

echo All done.
goto :eof


:process
set "ext=%~1"
set "ext=%~2"
set "ext=%ext:~0,99%"
md "%destdir%\%~2" >nul 2>nul
move "%~1*.*" "%destdir%\%~2"
echo %~1 %destdir%\%~2
goto :eof

I just dunno how to get the bat to read the season # in the file name, and then put the file in the correct subdirectory that correlates to the season # of the tv show.

Posted: 23 Nov 2009 15:49
by Boggie1688
Here is the final code

@echo off
set "sourcedir=C:\Test\unsorted"
set "destdir=C:\Test\tv_shows"


for /f %%a in (tv.txt) do (
for /f %%b in ('dir /s /b "%sourcedir%\*%%a*"') do (
for /f %%c in ('find "*S*.*" "%%b"') do call :process "%%b" "%%a" "%%c"
)
)

echo All done.
goto :eof


:process
set "ext=%~1"
set "ext=%~2"
set "ext=%~3"
set "ext=%ext:~0,99%"
echo %~1
echo %~2
echo %~3
md "%destdir%\%~2" >nul 2>nul
echo %destdir%\%~2
move "%~1*.*" "%destdir%\%~3\%~2"
echo %~1 %destdir%\%~3\%~2
goto :eof

I still can't get it to work. The third for command is to search the directory for a file name that contains the season. I wanna use that to label a subdirectory of the tv show in the sorted directory. Right now that command keep spitting out that access is denied.

Anyone know what that means?

Posted: 25 Nov 2009 11:11
by avery_larry
Boggie1688 wrote:Wow thanks for the reply.

Ok I just want to go over your code so I can understand it well enough to work on it. I would really appreciate it.


for /f %%a in (search.txt) do (
for /f %%b in ('dir /s /b /a-d "%sourcedir%\*.%%a"') do call :process "%%b"
)

Is %%a a variable for each line of text?
yes.
Hence its creating another variable %%b for C:\Unsorted\%%a?
not exactly. %%b is each filename returned by the command dir /s /b /a-d "c:\unsorted\*.%%a"

It says if there is a directory C:\Unsorted\%%a then run process and pass the variable %%b.
no. See above.
Process is where I get lost.
Why are there two sets? What do both of them do?
%~x1 returns the file extension of the %1 variable, which is passed to this subroutine by the for loop. %ext:~1,99% is how you get a substring of the variable -- this starts with the 2nd character in the variable and uses the next 99 characters. In effect, the 1st set command gets the extension of the filename passed to the subroutine, and the 2nd set command simply strips the leading period.
What does >nul 2>nul do for md?
It supresses all output of the md command. Most of the time the directory will already exist, which would generate an error message. Now the error message will be suppressed.
What does "%~1" stand for?
The ~ just gets rid of any surrounding double quotes. %1 is the first parameter passed to the subroutine.
And lastly :eof? Points too?
eof stands for End Of File. It just goes to the end of the file. You don't need an actual :eof label -- if you goto :eof it'll just skip to the end.

Posted: 25 Nov 2009 11:15
by avery_larry
Boggie1688 wrote:Err.. I messed up my explanation of the destination directory.

I'm looking to do

C:Unsorted/House/S01E02.mkv
C:Unsorted/House/S02E02.mkv
C:Unsorted/Stargate/S01E02.mkv
C:Unsorted/Stargate/S01E01.mkv
to
C:Sorted/House/Season 1/S01E02.mkv
C:Sorted/House/Season 2/S02E02.mkv
C:Sorted/Stargate/Season 1/S02E02.mkv
C:Sorted/Stargate/Season 2/S01E02.mkv

Will this fix that?

@echo off
set "sourcedir=H:\Test\unsorted"
set "destdir=H:\Test\tv_shows"


for /f %%a in (tv.txt) do (
for /f %%b in ('dir /s /b "%sourcedir%\*%%a*.txt"') do call :process "%%b" "%%a"
)
)

echo All done.
goto :eof


:process
set "ext=%~1"
set "ext=%~2"
set "ext=%ext:~0,99%"
md "%destdir%\%~2" >nul 2>nul
move "%~1*.*" "%destdir%\%~2"
echo %~1 %destdir%\%~2
goto :eof
No. what you're trying is vastly different from what I understood when you said "Files ending in S02 need to go to a folder named S02."

Posted: 25 Nov 2009 11:18
by avery_larry
How many do you have? Why not just create the sorted folder structure instead of trying to create it based on your content?

Then you can simply:

move c:\unsorted\house\s01* "c:\sorted\house\season 1\"
move c:\unsorted\house\s02* "c:\sorted\house\season 2\"


....

Posted: 27 Nov 2009 15:31
by Boggie1688
Hey Avery,

Sorry for the late reply was quiet busy yesterday.

I understood quite a bit of your code after fiddling around with it for a few days. Your pretty slick at it. I honestly have the feeling now that what I want to do might not be possible with a batch file.

Your suggestion of creating a sorted folder structure seems to be the only solution. I was just being lazy; every time a new season comes out means I have to go make a new season folder. LAZY! Multiple tv shows, with multiple season adds up to a huge directory structure.

Do you how I would search the file name to resolve the season, then place it in the right season folder that has already be made?
I need some type of statement that resolves the S** section of the file name, and then will use it to push to the right season folder. However none of my find or findstr commands seem to work. I have yet to work out what to do once I get a command that resolves the S** text.

Posted: 02 Dec 2009 13:03
by avery_larry
You could play around with substring manipulation. If you have a filename:

S01E02.mkv


and that's assigned to a variable fname, then:

%fname:~0,3% will be S01, and you can use an if statement to decide the directory to use

if /i "%fname:~0,3%"=="S01" (move "%fname%" "c:\sorted\house\season 1\")

Could also do a MD in there. If you really want to automate the whole thing, this should help you get there.

Posted: 03 Dec 2009 16:05
by Boggie1688
I've never heard of that command. But I'll give it a try.

I'm in the middle of finals, but when its over I'll be back on the horse.