Page 1 of 1

Copy files

Posted: 16 Jul 2009 02:09
by batchnoob
I want to Copy all *.jpg, *.txt, *.3pg, *.mp4 from C:\ D:\ E:\ F:\ G:\ and all there subfolders into the folders

I:\JPG\
I:\TXT\
I:\3PG\
I:\MP4\


Could you help me ? =)

Posted: 16 Jul 2009 19:17
by avery_larry
UNTESTED off the top of my head:

Code: Select all

for %%a in (c d e f g) do (
   for %%b in (jpg txt 3pg mp4) do (
      for /f "tokens=* delims=" %%c in ('dir /b /s %%a:*.%%b) do copy "%%c" i:\%%b
   )
)

Posted: 16 Jul 2009 23:16
by ghostmachine4
here's a vbscript

Code: Select all

Set objFS = CreateObject("Scripting.FileSystemObject")
Dim drive(5)
drive(0) = "c:\"
drive(1) = "d:\"
drive(2) = "e:\"
drive(3) = "f:\"
drive(4) = "g:\"

For i=LBound(drive) To UBound(drive)
   Set objFolder = objFS.GetFolder(drive(i))
   Go (objFolder)
   Set objFolder=Nothing
Next

Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders
         Go eFolder
    Next
   For Each strFile In objDIR.Files
      strFileName = strFile.Name
      strFilePath = strFile.Path
      strExtension = LCase(objFS.GetExtensionName(strFileName))
      If strExtension = "jpg" Then      
         destination = "I:\JPG"   
      ElseIf  strExtension = "txt" Then
         destination = "I:\TXT"    
      ElseIf strExtension = "3pg" Then
         destination = "I:\3PG"
      ElseIf strExtension = "mp4" Then
         destination = "I:\MP4"
      Else
         destination = ""
      End If
      If destination <> "" Then
         WScript.Echo "Copying " & strFileName & " to " & destination
         objFS.CopyFile strFilePath,destination & "\" & strFileName
      End If
      
   Next
  End If 
End Sub   


save as mycopy.vbs and on command line

Code: Select all

c:\> cscript /nologo mycopy.vbs 

Posted: 16 Jul 2009 23:20
by ghostmachine4
avery_larry wrote:UNTESTED off the top of my head:

Code: Select all

for %%a in (c d e f g) do (
   for %%b in (jpg txt 3pg mp4) do (
      for /f "tokens=* delims=" %%c in ('dir /b /s %%a:*.%%b) do copy "%%c" i:\%%b
   )
)


why not traverse the drive once , and check for extension. more efficient this way than having to traverse the same drive every time for one extension type.

Posted: 17 Jul 2009 09:19
by avery_larry
ghostmachine4 wrote:
avery_larry wrote:UNTESTED off the top of my head:

Code: Select all

for %%a in (c d e f g) do (
   for %%b in (jpg txt 3pg mp4) do (
      for /f "tokens=* delims=" %%c in ('dir /b /s %%a:*.%%b) do copy "%%c" i:\%%b
   )
)


why not traverse the drive once , and check for extension. more efficient this way than having to traverse the same drive every time for one extension type.
Why make 35 lines of code when 5 will do? Besides, windows does some type of cache when doing a dir /s. The first time on my machine a dir /s took 36 seconds (the program files directory). The next 3 took 1 second each -- even after waiting 10 minutes (without closing the DOS window).
Efficiency and simplicity are often at odds. KISS (Keep It Simple Stupid). I can't think of anything in DOS that wouldn't be significantly more complicated. Perhaps a dir /b /s piped through multiple findstr /v commands.

Actually, I can't think of any way in DOS to traverse the drive once and get all the different extensions without using a temp file--which may be less efficient than multiple dir /s commands.

Never mind -- you could do 4 separate comparisons to every individual file on a single dir /b /s drive:\*.*. I'd have to test to see if that is more efficent than allowing the dir command to find it's own wildcard matches multiple times. Clearly much more complicated (in my opinion).

Posted: 17 Jul 2009 11:33
by ghostmachine4
avery_larry wrote: I can't think of anything in DOS that wouldn't be significantly more complicated. Perhaps a dir /b /s piped through multiple findstr /v commands.
Actually, I can't think of any way in DOS to traverse the drive once and get all the different extensions without using a temp file--which may be less efficient than multiple dir /s commands.

dir can take in multiple file extension. that's why i suggested, remove the for loop for the file types. something like this

Code: Select all

for ... ( c d e f g ) do  (
   for .... ( dir /b /s *.mp3 *.jpg *.blah ) do
      get file extension using  %~xI ???
      if extension == mp3 (
           move to somefolder....
      )else(
           and so on
      )
   )
)

there's also no need to use findstr as we are not looking into files to search for strings ( or are we??? )

Posted: 17 Jul 2009 21:30
by avery_larry
findstr idea would be used on the output of dir /b /s like this:

dir /b /s c:\*.* | findstr <endoflinesyntax>.mp3 (so not finding contents of files)

You can put multiple matches in a file and feed the file to findstr (but that would be a tempfile)

I guess it probably comes down to personal preference. I'm not convinced that traversing once is a benefit because then you have to do multiple (on average) compare operation to determine the extension and then copy the file. Perhaps if disk cost was extremely high and/or windows didn't cache the results anyway and/or you had a LOT of files it might be worth the effort.

Maybe I'll see what happens when running on a network drive.

Posted: 17 Jul 2009 22:22
by ghostmachine4
avery_larry wrote: I'm not convinced that traversing once is a benefit because then you have to do multiple (on average) compare operation to determine the extension and then copy the file.

string comparison can be done using cmd.exe's internals. eg if/else, set , for loop etc. . Also dir is built into cmd.exe so using it to find files of some type is way faster than piping each individual file to findstr , which is an external command. the pipe will already cost you overheads.

Posted: 17 Jul 2009 22:26
by avery_larry
Network drive:

dir /b /s *.1 *.2 *.3 *.4

Took 5 minutes.

dir /b /s *.1
dir /b /s *.2
dir /b /s *.3
dir /b /s *.4

Took 11 minutes.

So to that end (still UNTESTED):

Code: Select all

@echo off
setlocal enabledelayedexpansion
for %%a in (c d e f g) do (
   cd /d %%a:\
   for /f "tokens=* delims=" %%b in ('dir /b /s *.jpg *.txt *.3pg *.mp4') do (
      set ext=%%~xb
      copy "%%~b" i:\!ext:~1,4!
   )
)

Posted: 17 Jul 2009 22:57
by ghostmachine4
that's just about it. thumbs up for that verification.
dir can also include /a-d to skip checking directories, but that's just trivial.