Computer Hope

Software => Computer programming => Topic started by: eddie.ceri on April 07, 2010, 02:10:01 PM

Title: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 02:10:01 PM
I would appreciate any help to speed up a very mundane task.

I would like to find or write a batch file to do the following:

1. find all jpegs in a specific folder,
2. for each jpeg in the folder read the "date picture taken" attribute,
3. create a folder with the name as the date the picture was taken,"YYYY_MM_DD"
4. move each picture into its new folder,
5. Then move all folders to a different directory.

I might be asking a bit much but it doesn't sound simple to me as im a complete novice.

Can anyone help me or point me in the right direction.
Title: Re: Batch file to save photos into folders
Post by: Sidewinder on April 07, 2010, 04:16:37 PM
I'm very skeptical that a batch file would be of help here. The "Date Picture Taken" property is not exposed in batch code. This little snippet will overcome that shortcoming:

Code: [Select]
folderName = "c:\Pictures"                'check for valid directory

Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(folderName)

Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder(folderName)
Set fc = f.Files

For Each fs In fc
   If fso.GetExtensionName(fs) = "jpg" Then
      Set objFolderItem =  objFolder.ParseName(fs.Name)
      strValue = objFolder.GetDetailsOf(objFolderItem, 25)
 
      If strValue <> "" Then
      newYY = DatePart("yyyy", strValue)
      newMM = DatePart("m", strValue)
      If newMM < 10 Then newMM = "0" & newMM
      newDD = DatePart("d", strValue)
    If newDD < 10 Then newDD = "0" & newDD
    newFolder = "c:\" & newYY & "_" & newMM & "_" & newDD    'check for valid drive and path

If Not fso.FolderExists(newFolder) Then
  fso.CreateFolder(newFolder)
End If
 
  fso.CopyFile fs.Path, newFolder & "\"
    End If
End If
Next

The lines are marked that need to be changed. folderName is the directory where the pictures are now. newFolder is where you want the pictures to be.

Step 5 of your request is a duplicate step 4. Instead of copying files to an interim directory, why not just send them to their final resting place with a single instruction?

Save the script with a vbs extension and run from the command prompt as cscript scriptname.vbs

I dislike trashing files (especially pictures with sentimental value), so I used the copyfile method. You can change this to movefile method.

Good luck.  8)

Sorry about the code alignment. It looked great in my editor.  ;D
Title: Re: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 04:34:29 PM
I have copied into a notepad file and changed ext to .vbs and it worked partially .

3 jpegs were moved to their correct folder however ther was 100+plus left behind.....

many thanks for your help sof far by the way im light years further than i was...

the 3 that moved were .jpg whilst the remainder were .JPG does the case make any difference?
Title: Re: Batch file to save photos into folders
Post by: BC_Programmer on April 07, 2010, 04:37:55 PM
the 3 that moved were .jpg whilst the remainder were .JPG does the case make any difference?

it would appear so.


Change the line:

Code: [Select]
   If fso.GetExtensionName(fs) = "jpg" Then


to:
Code: [Select]
   If lcase(fso.GetExtensionName(fs)) = "jpg" Then
Title: Re: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 04:40:27 PM
I did try:
                    If fso.GetExtensionName(fs) = "jpg" or "JPG" Then

but it didnt recognise the string JPG.....
Title: Re: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 04:44:56 PM
Well ...... I would like to say a big thank you to sidewinder for his time and effort and for BC_Programmer for his fine tuning........

Many thanks.....

 All i have to do now is decifer how the beast works....
Title: Re: Batch file to save photos into folders
Post by: Helpmeh on April 07, 2010, 04:47:57 PM
This could work...not quite sure...it depends on the camera.

@echo off
setlocal enabledelayedexpansion
for /f "skip=5 tokens=1,5" %%A in ('dir /t:c *.jpg') do (
echo Date --- %%A
echo File --- %%B
     if not "%%B"=="" if not "%%B"=="free" (
          set filedate=%%A
          set filedate=!filedate:/=-!
          if not exist !filedate! md !filedate!
          copy %%B !filedate!
     )
)
pause

Seems to work for me.

I just felt like making an all-batch solution.
Title: Re: Batch file to save photos into folders
Post by: BC_Programmer on April 07, 2010, 04:50:12 PM
I did try:
                    If fso.GetExtensionName(fs) = "jpg" or "JPG" Then

but it didnt recognise the string JPG.....

That isn't proper syntax. the "Or" operator only works on Booleans or numeric variables.

in order for it to work here you'd need to use:

Code: [Select]
If fso.GetExtensionName(fs) = "jpg" or fso.GetExtensionName(fs)="JPG" Then

However, it still wouldn't work for mixed case, like jPg or Jpg or JPg, etc.

using lcase or ucase to convert the case before comparison, however, fixes that.

*Note:

Previously, me and Geek-9pm, another member, got in a rather heated debate with regards to this particular usage. my stance was that it was best to use StrComp() to compare strings,rather then case conversions. this was based on the fact that StrComp() would recognize combined glyphs such as the combined "AE" character properly being matched to the actual two characters, AE.

However, it would appear, from what I've read in the meantime regarding StrComp, that while this would work, it is slower (another incorrect contention I held was that the StrComp() method was faster). StrComp() is designed for comparing strings for sorting algorithms; this is why it returns a value indicating the sort order of the two items.

Therefore, if geek-9pm is reading this, I was WRONG  ;D


This could work...not quite sure...it depends on the camera.

@echo off
setlocal enabledelayedexpansion
for /f "skip=5 tokens=1,5" %%A in ('dir /t:c *.jpg') do (
echo Date --- %%A
echo File --- %%B
     if not "%%B"=="" if not "%%B"=="free" (
          set filedate=%%A
          set filedate=!filedate:/=-!
          if not exist !filedate! md !filedate!
          copy %%B !filedate!
     )
)
pause

Seems to work for me.

I just felt like making an all-batch solution.

No, that won't work. "Date Picture Taken" is an EXIF attribute, and while the actual date of the picture can be used for  this it breaks down when that file is copied or moved, whereas the EXIF data stays intact.


Title: Re: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 04:59:14 PM
I have just test run the .vbs file and it works great ...........

there are a few ponts that i didnt think would be a problem but might cause issues.....

      1.     If a file with the same name is already in that folder (probably the same file anyway) the whole routine doesnt run it creates an error message   "Microsoft VBScript runtime error: File already present"   which is common sense i suppose.
   
      2.    What i would prefer if it didnt copy it and allowed me to sort it out manually later but carried on with the rest of the jpegs.
Title: Re: Batch file to save photos into folders
Post by: BC_Programmer on April 07, 2010, 05:18:06 PM
I have just test run the .vbs file and it works great ...........

there are a few ponts that i didnt think would be a problem but might cause issues.....

      1.     If a file with the same name is already in that folder (probably the same file anyway) the whole routine doesnt run it creates an error message   "Microsoft VBScript runtime error: File already present"   which is common sense i suppose.
   
      2.    What i would prefer if it didnt copy it and allowed me to sort it out manually later but carried on with the rest of the jpegs.

Good idea. I just added an "On Error Resume Next" statement.

Code: [Select]
folderName = "c:\Pictures"                'check for valid directory

Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(folderName)

Set fso = CreateObject("Scripting.FileSystemObject")

Set f = fso.GetFolder(folderName)
Set fc = f.Files

For Each fs In fc
   If fso.GetExtensionName(fs) = "jpg" Then
      Set objFolderItem =  objFolder.ParseName(fs.Name)
      strValue = objFolder.GetDetailsOf(objFolderItem, 25)
 
      If strValue <> "" Then
      newYY = DatePart("yyyy", strValue)
      newMM = DatePart("m", strValue)
      If newMM < 10 Then newMM = "0" & newMM
      newDD = DatePart("d", strValue)
    If newDD < 10 Then newDD = "0" & newDD
    newFolder = "c:\" & newYY & "_" & newMM & "_" & newDD    'check for valid drive and path

If Not fso.FolderExists(newFolder) Then
  fso.CreateFolder(newFolder)
End If
                                On Error Resume Next
  fso.CopyFile fs.Path, newFolder & "\"
    End If
End If
Next

It is also possible to create a logfile of the files that were missed.
Title: Re: Batch file to save photos into folders
Post by: eddie.ceri on April 07, 2010, 05:36:19 PM
That worked great.......

The log would be good,     

I have removed any duplicate jpgs by using the "Easy duplicate finder" application.

Many thanks for your time and effort BC_Programmer
Title: Re: Batch file to save photos into folders
Post by: ghostdog74 on April 07, 2010, 07:36:52 PM
I would appreciate any help to speed up a very mundane task.

I would like to find or write a batch file to do the following:

1. find all jpegs in a specific folder,
2. for each jpeg in the folder read the "date picture taken" attribute,
3. create a folder with the name as the date the picture was taken,"YYYY_MM_DD"
4. move each picture into its new folder,
5. Then move all folders to a different directory.

I might be asking a bit much but it doesn't sound simple to me as im a complete novice.

Can anyone help me or point me in the right direction.

you can download jpeg tools like jhead for example, and then run your photos with jhead using  for loop and grab the images creation date/time, do some manipulation with the date/time to the format you want, and then use mkdir to create directories etc etc...