Learn about Windows PowerShell
Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to obtain metadata from photo files.
Hey, Scripting Guy! I need some help. I have thousands of photo files on my computer. I need to bring some order to them. I know that I can use Get-ChildItem from Windows PowerShell, and I can find the size of files and names of files. But I need to access information that is more specific to the photos, such as what camera was used, what the F-stop was, and the photo resolution. I know there are expensive software programs that might provide this information, but the information must come from somewhere, and maybe, just maybe, you can tell Windows PowerShell where that location is?
Microsoft Scripting Guy, Ed Wilson, is here. It is just a couple days until the Windows PowerShell Saturday event in Charlotte. If you have not yet registered, I think there are a couple of tickets left, so don’t delay too much or they will be gone. The list of speakers reads like a who’s who in the Windows PowerShell world. In fact, six of the speakers at our event in Charlotte are also going to be speaking at the Windows PowerShell Summit in Seattle in April. To register, go to PowerShell Saturday #007.
Note This is the fourth in a series of posts that talk about working with files and folders by using Windows PowerShell. You should read the previous posts:
Commonly filled out metadata for image files contains the camera, the F-stop, resolution, and other useful information about the photo. This can be extremely useful for anyone who takes photos. The image metadata is easily found from the File tab for the photo by clicking Properties, then Details. The following image shows typical photo metadata:
When using the content view in File Explorer in Windows 8.1, a thumbnail appears with the dimensions of the photo, as shown here:
To use Windows PowerShell to examine this type of metadata means using the Shell.Application COM object, connecting to a file, and then walking through the metadata property bag. This technique is a bit cumbersome. Luckily, I can use the same function I wrote yesterday to accomplish this task.
Note The complete Get File Metadata function is available on the Script Center Repository.
Because it is possible that the script needs to iterate through thousands of photos, and for each photo it needs to search several hundred metadata attributes, the script will take some time to run. The best thing to do is to store the results in a variable. This will allow sorting and post collection processing of the data following the run.
The Get-FileMetaDataReturnObject.ps1 script contains a single function. The function is the Get-FileMetadata function. I load the function in the Windows PowerShell ISE, and run it to copy the function into memory. After I have done that, I call the function and pass it an array of folder paths. I get the array of folder paths by using the Get-ChildItem cmdlet. Here is the command that performs a recursive lookup of a folder named pics and pulls out the directory paths in that folder. This is a single line command that has wrapped.
$picMetadata = Get-FileMetaData -folder (Get-childitem E:\pics -Recurse -Directory).FullName
After the function completes running, I examine the contents of the $picMetaData variable to see what pieces of metadata are filled out. As shown in the following image, there is a decent amount of metadata supplied:
After perusing the list of metadata, I decide that I am interested in the camera model, dimensions of the photo, the f-stop, flash mode, iso speed, exposure time, focal length, size, and of course, the path to the photo. It is as easy as picking out chocolates from a candy box. Because I have stored the returned objects in the $picMetadata variable, I pipe it to the Select-Object cmdlet to produce the output. The command is shown here (this is a single-line command that has wrapped):
Select 'camera model', dimensions, f-stop, 'flash mode', 'iso speed', 'exposure time', 'focal length', size, path
The command and its associated output are shown in the following image:
Now that I know that the command produces the output I desire, I pipe the results to the Export-CSV cmdlet as shown here (this is a single-line command):
Select 'camera model', dimensions, f-stop, 'flash mode', 'iso speed', 'exposure time', 'focal length', size, path |
Export-CSV -Path c:\fso\photoMetadata.csv -NoTypeInformation
Now, I use the Invoke-Item cmdlet to open the CSV file in Microsoft Excel. This command is shown here:
I can now use Microsoft Excel to examine and analyze the metadata associated with my photos. The following image illustrates this technique:
RR, that is all there is to using Windows PowerShell to obtain photo metadata. File Week will continue tomorrow when I will talk about finding neglected files.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
File/photo metadata stuff should have been built into Powershell 4.0 in my opinion
Looks very handy. Just tried this and got as far as setting and calling the $picMetaData for a folder. It didn't list anything when i just has a TIF file in there but when i created a jpg version of the same file it listed the details of both. Tried deleting
the jpg and back to no listing. Apologies if i'm missing something as a Powershell lightweight
I looked into a lot of these kinds of methods including some others, but ended up mixing in a utility I've used for years (ExifTool) and using it's XML output to get it into PowerShell. Wrote it up at http://www.jeuch.com/wp/2014/04/05/powershell-and-image-meta-information-even-raw/ if anyone is interested.
Worth noting when a script requires WMF 3.0
newbie alert... more photographer than programmer but attempting to learn how to use Powershell for managing thousands of files based on metadata. this looks very promising to me.
Unfortunately I haven't been able to get this example to run, so thought I'd ask for a little help. Thank you in advance.
I've loaded Get-FileMetaDataReturnObject into memory and then attempt to use it as show above but get the following:
PS C:\Windows\system32> $picMetadata = Get-FileMetaData -folder (Get-childitem C:\test -Recurse -Directory).FullName
Get-ChildItem : A parameter cannot be found that matches parameter name 'Directory'.
At line:1 char:83
+ $picMetadata = Get-FileMetaData -folder (Get-childitem C:\test -Recurse -Directory <<<< ).FullName
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I'm sure I'm missing something obvious here, but have spent a lot of time trying to figure this out and one of you will probably know my problem instantly. Thx!
@John, The -Directory parameter is available in powershell v2 and above.