Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2616
  • Last Modified:

Work on files in subdirectories: batch or VBScript

Hi all

I'd like to script quite a complex process... preferably using a batch file but VBScript would probably be OK, I'm just less familiar with it.

We've got a network location filled with audio files in the format:

\\servername\audio\DD-MM-YY\HH-MM-SS.mp2

The mp2 files are 15 minutes long so there are 96 files in each DD-MM-YY folder, and there are a fixed number of day folders.  As a new day is created the oldest is deleted.

I want to create a mirror of the entire tree - but I also want to convert the files to a lower quality sample rate.  I can convert individual files using lame.exe like this: (which creates a 16Kbps mono file)

lame --mp2input -m m -a -b 16 file.mp2 file.mp3

I can also convert entire folders using wildcards.

The problem with scripting the process is that every day a new folder is created, and the oldest folder is deleted, so the tree is always changing.

I'm sure it's possible to write a batch file along the lines of:

For every folder in the root
  For every file in the folder
   Lame command as above
  Next
Next

But I don't know the syntax...

Also:

I don't want to process files if they already exist in the destination - and I want the process to remove folders from the destination if they no longer exist in the source.

The destination filename will be the same as the source filename, but the extension will be different - sources end in .mp2 - destinations end in .mp3

I could probably use robocopy.exe to do the mirror process and convert afterwards, which would work if robocopy can be told to only rely on filenames BEFORE the extension, and ignores the fact that the files are actually different - but I would still need to know how to convert files in a changing tree!

Any suggestions?

Thanks !


Simon
0
SimonUK
Asked:
SimonUK
1 Solution
 
PaulCaswellCommented:
Hi SimonUK,

Can I suggest you post a pointer question here:

http://www.experts-exchange.com/Operating_Systems/MSDOS/

If you dont know how, look in the help pages or post here.

Paul
0
 
SimonUKAuthor Commented:
Good idea - thanks !

Simon
0
 
JesterTooCommented:
This VBScript will accomplish what you want...

HTH,
Lynn

'*****************************************************************************************
' convert.vbs
'
'  This script backups all MP2 files found within a source folder tree to a target folder
'  tree of identical structure.  MP2 files are converted to MP3 files in the target folders
'  and only those MP2 files which have not yet been converted are operated on.  New target
'  folders are created as necessary and old ones removed to enforce that the target folder
'  structures stay synchronized.
'
'  Lynn Ransdell  05/21/2006
'
'*****************************************************************************************

Option Explicit

Dim oFSO, oShell
Dim SourceRoot, TargetRoot
Dim buFileCount, ofFileCount
Dim aSrcFolders, aTgtFolders
Dim Folder
Dim StopNow, n

'' SourceRoot  = "E:\ee\source"           '<=== my test folder
'' TargetRoot  = "E:\ee\target"           '<=== my test folder
   SourceRoot  = "\\servername\audio"     '<=== change as necessary
   TargetRoot  = "\\servername\audio2"    '<=== change as necessary
   buFileCount = 0
   ofFileCount = 0

   Set oFSO = CreateObject("Scripting.FileSystemObject")
   Set oShell = CreateObject("Wscript.Shell")

   '-- determine if directory root structures exist...

   If Not oFSO.FolderExists(SourceRoot) Then
      Wscript.Echo "Path to root of SOURCE is invalid."
      StopNow = True
   End If

   If Not oFSO.FolderExists(TargetRoot) Then
      Wscript.Echo "Path to root of TARGET is invalid."
      StopNow = True
   End If

   If StopNow Then
      Wscript.Echo "Terminating due to error(s)."
      Set oFSO = Nothing
      Set oShell = Nothing
      Wscript.Quit(16)
   End If

   '-- ensure that all folders exist under TARGET
   aSrcFolders = GetFolders(SourceRoot)
   For n = 0 To UBound(aSrcFolders)
      Folder = TargetRoot & aSrcFolders(n)
      If Not oFSO.FolderExists(Folder) Then
         oFSO.CreateFolder Folder
      End If
   Next

   '-- remove any TARGET folders that no longer exist under SOURCE
   aTgtFolders = GetFolders(TargetRoot)
   For n = 0 To UBound(aTgtFolders)
      Folder = SourceRoot & aTgtFolders(n)
      If Not oFSO.FolderExists(Folder) Then
         oShell.Run("cmd /c rd /s /q " & TargetRoot & aTgtFolders(n)),0
      End If
   Next

   '-- Let's get to work...
   For n = 0 To UBound(aSrcFolders)
      ScanFiles SourceRoot & aSrcFolders(n), TargetRoot & aSrcFolders(n)
   Next

   Wscript.Echo "Finished!  " & buFileCount & " files backed up."

   Set oFSO = Nothing
   Set oShell = Nothing

Sub ScanFiles(SrcPath, DestPath)
Dim oFolder, colFiles
Dim FileName, oFile
Dim SrcFile, oSrcFile
Dim DestFile, oDestFile
Dim n

   Set oFolder = oFSO.GetFolder(SrcPath)
   Set colFiles = oFolder.Files
   For Each oFile In colFiles
      FileName = oFile.Name
      If LCase(Right(FileName, 4)) = ".mp2" Then
         SrcFile = SrcPath & "\" & FileName
         Set oSrcFile = oFSO.GetFile(SrcFile)
         DestFile = DestPath & "\" & FileName
         DestFile = Left(DestFile,Len(DestFile)-1) & "3"

         If Not oFSO.FileExists(DestFile) Then
            RunLame SrcFile, DestFile
         End If
      End If
   Next

   Set oSrcFile = Nothing
   Set oDestFile = Nothing
   Set colFiles = Nothing
   Set oFolder = Nothing

End Sub

Function GetFolders(BaseFolder)
Dim oBaseFolder
Dim SubFolder
Dim strArr

   Set oBaseFolder = oFSO.GetFolder(BaseFolder)
   For Each SubFolder In oBaseFolder.SubFolders
      If Not IsEmpty(SubFolder) Then
         strArr = strArr & "+" & Mid(SubFolder, Len(BaseFolder) + 1)
      End If
   Next

   GetFolders = Split(Mid(strArr, 2), "+")
   Set oBaseFolder = Nothing

End Function

Sub RunLame(SrcFile, DestFile)
Dim sCommand

''sCommand = "cmd /c copy                   " & SrcFile & " " & DestFile
  sCommand = "lame --mp2input -m m -a -b 16 " & SrcFile & " " & DestFile
  oShell.Run(sCommand),0,True
  buFileCount = buFileCount + 1

End Sub
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
SimonUKAuthor Commented:
That's amazing - thanks for all your help in such detail, so quickly!

Will award points without testing it but will post back with results as soon as I've tried the script out.

Thanks again !


Simon
0
 
JesterTooCommented:
Thanks for the compliments, Simon.  Actually, this is a variation/simplification of another script I had written some time ago that performed a task very similar to yours.

Let me know if you discover any problems with it.  Even though I tested it with aout a half-dozen scenarios there is always an opportunity for Mr. Murphy to appear!

Note that I didn't test it by running LAME since I don't use that software.  Instead, I substituted the copy command as you can still see commented out near the bottom of the script.

Also, this script doesn't handle folder trees that are deeper than 1 level (it could with recursion but I removed that as part of the simplification) but your scenario doesn't indicate that it is needed.

Thanks for the grade!
Lynn
0
 
SimonUKAuthor Commented:
Hi Lynn

Almost there!

When I run the script, the directory structure is mirrored but no files are placed in them.  The script reports xxxx files converted (about 1500 at the moment) and lame.exe appears briefly in Task Manager.

When Lame is run manually, it opens a command window and displays progress.  In a scripted situation I would normally expect the Lame window to appear, run through the progress then disappear and re-appear with the next file called by the script.

I'm guessing the problem may be a space that exists in the root source path, which is along the lines of:

"\\servername\audio\192.168.1.1\audio\audio here"

When you pass the command to lame.exe, the path needs to be in quotes otherise Lame thinks there are too many options, but I don't know enough about VBScript to know whether this script does that or not, or how to check it.

I'm just creating a test source folder with no spaces to check the theory !

Simon
0
 
SimonUKAuthor Commented:
Update...

My test path "\\servername\audio\192.168.1.1\audio\test" works fine... so it's the space in the path causing the problem.  I can't easily remove that, unfortunately - is it possible to add quotes to the path given to Lame ?

Also interesting is that the Lame progress window doesn't appear, which is fine except it would be good to have some indication that the script was running.  I appreciate VBS doesn't really allow for much user interaction but is it possible to have the script display a box saying "Conversion running:  XXXX files processed", even if it's just a dos box?

The following note I will post as a separate question, because it's additional and I feel needs more points - but just so you're aware in advance! :

It would also be really handy to have the script generate a log as it goes, in the same way echo can add lines to a text file, just detailing something like:

21/05/2006 10:47 00-00-00.mp2 -> 00-00-00.mp3

and errors like:
21/05/2006 10:45 ERROR!  No destination root path

Or whatever can be easily pulled from the existing variables.  I can then write a batch file to mail this log to me.

Thanks !


Simon
0
 
cwwkieCommented:
> is it possible to have the script display a box saying "Conversion running:  XXXX files processed", even if it's just a dos box?

Take a look at the following script:

if instr(1,wscript.fullname,"cscript.exe",vbtextcompare) = 0 then
    Set WshShell = CreateObject("WScript.Shell")
    WshShell.Run "CSCRIPT.EXE //nologo " & Chr(34) & WScript.ScriptFullName & Chr(34)
    WScript.Quit
End If

For i=1 to 5
  wscript.stdout.writeLine "Processing File " & i
  WScript.Sleep 1000
Next

wscript.stdout.write "Press Enter "
wscript.stdin.readline
0
 
JesterTooCommented:
Hello, Simon... just got in from work and saw your posts.

Sorry about not handling the paths with embedded spaces... I really need to get in the habit of coding for that!  I NEVER use path or file names with spaces and I really wish that MS hadn't permitted that atrocity!!! but, it's a fact of life and we have to endure it I suppose.

Here is a slightly modified version of the script which addresses all your concerns except for the logging.  I will post that in the other question you've opened if I can find it... otherwise, I will just post it in this one later.  Oddly, removing a "logging" feature was one of the simplifications I had made to the script before originally posting.

As for the command shell window not displaying when LAME was processing... I plead guilty to that charge... I did it intentionally because seeing all those popups is usually pretty annoying.  But, I should have put something else in place to inform the user what was taking place.  You can now run it either way... just look at the value assigned to the variable "nHide" very near the bottom of this modified script.

'*****************************************************************************************
' convert.vbs
'
'  This script backups all MP2 files found within a source folder tree to a target folder
'  tree of identical structure.  MP2 files are converted to MP3 files in the target folders
'  and only those MP2 files which have not yet been converted are operated on.  New target
'  folders are created as necessary and old ones removed to enforce that the target folder
'  structures stay synchronized.
'
'  Lynn Ransdell  05/21/2006
'
'  NOTE:  This script makes extensive use of the "Wscript.Echo" statement.  Therefore,
'         in order to avoid an interactive dialogue that you must acknowledge for each
'         message, be sure to run this script like this:
'
'             cscript convert.vbs
'
'*****************************************************************************************

Option Explicit

Dim oFSO, oShell
Dim SourceRoot, TargetRoot
Dim buFileCount, ofFileCount
Dim aSrcFolders, aTgtFolders
Dim Folder
Dim StopNow, n

'' SourceRoot  = "E:\ee\source dir"       '<=== my test folder
'' TargetRoot  = "E:\ee\target dir"       '<=== my test folder
   SourceRoot  = "\\servername\audio"     '<=== change as necessary
   TargetRoot  = "\\servername\audio2"    '<=== change as necessary
   buFileCount = 0
   ofFileCount = 0

   Set oFSO = CreateObject("Scripting.FileSystemObject")
   Set oShell = CreateObject("Wscript.Shell")

   '-- determine if directory root structures exist...

   If Not oFSO.FolderExists(SourceRoot) Then
      Wscript.Echo "Path to root of SOURCE is invalid."
      StopNow = True
   End If

   If Not oFSO.FolderExists(TargetRoot) Then
      Wscript.Echo "Path to root of TARGET is invalid."
      StopNow = True
   End If

   If StopNow Then
      Wscript.Echo "Terminating due to error(s)."
      Set oFSO = Nothing
      Set oShell = Nothing
      Wscript.Quit(16)
   End If

   '-- ensure that all folders exist under TARGET
   aSrcFolders = GetFolders(SourceRoot)
   For n = 0 To UBound(aSrcFolders)
      Folder = TargetRoot & aSrcFolders(n)
      If Not oFSO.FolderExists(Folder) Then
         oFSO.CreateFolder Folder
      End If
   Next

   '-- remove any TARGET folders that no longer exist under SOURCE
   aTgtFolders = GetFolders(TargetRoot)
   For n = 0 To UBound(aTgtFolders)
      Folder = SourceRoot & aTgtFolders(n)
      If Not oFSO.FolderExists(Folder) Then
         oShell.Run("cmd /c rd /s /q " & Chr(34) & TargetRoot & aTgtFolders(n) & Chr(34)),0
      End If
   Next

   '-- Let's get to work...
   For n = 0 To UBound(aSrcFolders)
      ScanFiles SourceRoot & aSrcFolders(n), TargetRoot & aSrcFolders(n)
   Next

   Wscript.Echo "Finished!  " & buFileCount & " files backed up."

   Set oFSO = Nothing
   Set oShell = Nothing

Sub ScanFiles(SrcPath, DestPath)
Dim oFolder, colFiles
Dim FileName, oFile
Dim SrcFile, oSrcFile
Dim DestFile, oDestFile
Dim n

   Set oFolder = oFSO.GetFolder(SrcPath)
   Set colFiles = oFolder.Files
   For Each oFile In colFiles
      FileName = oFile.Name
      If LCase(Right(FileName, 4)) = ".mp2" Then
         SrcFile = SrcPath & "\" & FileName
         Set oSrcFile = oFSO.GetFile(SrcFile)
         SrcFile = Chr(34) & SrcFile & Chr(34)
         DestFile = DestPath & "\" & FileName
         DestFile = Left(DestFile,Len(DestFile)-1) & "3"

         If Not oFSO.FileExists(DestFile) Then
            DestFile = Chr(34) & DestFile & Chr(34)
            RunLame SrcFile, DestFile
         End If
      End If
   Next

   Set oSrcFile = Nothing
   Set oDestFile = Nothing
   Set colFiles = Nothing
   Set oFolder = Nothing

End Sub

Function GetFolders(BaseFolder)
Dim oBaseFolder
Dim SubFolder
Dim strArr

   Set oBaseFolder = oFSO.GetFolder(BaseFolder)
   For Each SubFolder In oBaseFolder.SubFolders
      If Not IsEmpty(SubFolder) Then
         strArr = strArr & "+" & Mid(SubFolder, Len(BaseFolder) + 1)
      End If
   Next

   GetFolders = Split(Mid(strArr, 2), "+")
   Set oBaseFolder = Nothing

End Function

Sub RunLame(SrcFile, DestFile)
Dim sCommand
Dim nHide

   nHide = 0   ''' 0 = hide the command shell window, 1 = don't hide

'' sCommand = "cmd /c copy                   " & SrcFile & " " & DestFile
   sCommand = "lame --mp2input -m m -a -b 16 " & SrcFile & " " & DestFile
   oShell.Run(sCommand),nHide,True
   buFileCount = buFileCount + 1

   ' if not showing the command shell, then tell the user what is happening
   If nHide = 0 Then
      Wscript.Echo "Converting file # " & buFileCount & " = " & DestFile
   End If

End Sub
0
 
SimonUKAuthor Commented:
Thanks Lynn

I agree on paths with spaces.  Unfortunately the audio path is generated by the system that is doing the recording, which names it after whatever the item is called... and because that name tends to be 'friendly', so is the path !

Anyway, it's running now and looking great - thanks!

New question being placed shortly.  I'll link back to this one for reference and try to link from here to the other question too.

cwwkie - thanks for your comment, the points had already been awarded but I do appreciate your input.


Simon
0
 
SimonUKAuthor Commented:
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now