You can use a shell script inside an Automator Quick Action to add the date of a file to the beginning of the file's name. You can also make this work with photos using the date the photo was taken from the metadata in the file. As a Quick Action you can easily apply this name change to one or many files at once.
You can also watch this video at YouTube.
Watch more videos about related subjects: Automator (50 videos).
You can also watch this video at YouTube.
Watch more videos about related subjects: Automator (50 videos).
Video Transcript
Hi this is Gary with MacMost.com. Today I want to show you how to write a Shell Script for Automator that will rename files using the date of the file or photo.
MacMost is brought to you thanks to a great group of supporters. Go to MacMost.com/patreon. There you can read more about it. Join us and get exclusive content.
So what if you wanted to rename a file adding the date of the file before the existing file name or if these are photos using the date that the photo was taken stored in the metadata for the file. You can do that using a Shell Script. Then the easiest was to access it is to put the shell script inside of Automator in a Quick Action. Then you can easily apply it to one or many files.
So here I have a folder called Pics. Here are the contents and the first thing is I want to use the date created. I don't see that here. I going to do View, Show View Options. Then I can see one of the options is to see Date Created. I'll turn that on. So now I can the created a date for all these files. I want to add these to the file name. So I could do that using a shell script. What I'm going to do is put that in Automator so I can have it as a service and easily apply it.
So first here I am in Terminal and I'm in the same folder. If you're not in that folder you can just do CD for change directory. Drag the folder there and then hit Return. Now you're in that directory. Now to get the date created in the Terminal you can use this stat command. Paste it here. stat dash f, for file, and then %B and then the name of the file. So this is the name of one of the files here. You could see the third one. When I hit Return you can see I get the creation date. So good. Right. Well, what's the number mean. It is the number of seconds since January 1, 1970. I want to have a nice looking date. Something I could read so I can use the Date command to format that. So we'll do this. Date dash r, then we'll put in parentheses what we were doing before with a dollar sign there. So it's going to basically going to take the results of this stat command and then put it through date dash r which will return a nice looking date. There it is. Tuesday, Dec 17, the time and the time zone and the year.
It's still not quite what we want it to be as a file name. So we can format it. We can tell the date command to do a little more formatting to get exactly what we want. Now I'm going to do the same command but afterwards I'm going to put this at the end +% capital Y, for year, a dash % lower case m for the month dash % d for the date, lower case there. Now we get a date that looks like that. That is what we want to put at the beginning of each file. So now we know how to get that.
Now we need to write a shell script that will actually put that as the name of the file. So let's switch into Automator. What I've done in Automator is I've created a new Quick Action Automator document. I've set it to receive files or folders in the Finder. Then I've added one thing here. Just this run shell script. You can see here if you search for it and drag it over. Now you end up with an area that you can write the shell script in. You can set the shell to what you want by default and maybe bash. I'm going to use zsh, z shell, because that's the default now in Catalina. This will probably work in either zsh or bash. So in this I'm going to set the shell script to Pass input as arguments. It's very important to change that because otherwise the default is standard in. You want to do it as arguments. So then you have a for loop that can loop through the arguments which are represented by the dollar sign and the at symbol there.
It's going to loop through everything that's into it. Which will be files and folders. It's going to do, it's going to loop, and then it's going do exactly what we just did in Terminal. But it's going to set that to a variable. The variable is file date. So file date equals. It's important not to have spaces around the equals there. We're also going to get the path to file and the file name itself.You do that by doing file name is $f, that the f from here looping through all of the files that has passed in. Then you do colon t and then file path is colon h.
Then we're going to do a simple mv command which is move. Move a file. You can use the move command to also rename files. All rename is is moving a file from one place to another with a new name, right. So we'll do the filepath slash and then in curly brackets we'll put the two different names. The first one is the original name and the second one is the new name. So the original name in quotes here is simply going to be the filename. The original filename. The second one is also going to be the original filename but before it is going to be the filedate what we got from the date and stat there. There's going to be a space between them. I have a space there.
So it's going to just loop through all the files passed in and rename them. This is called Rename File with Creation Date. That's what I called it. So if I Save that and then go back here to this folder I can select a file. I can Control click on it and you can see Quick Actions. Under Quick Actions there's Rename File with Creation Date. I'll select that and it runs the script and you can see what it does. It puts the date there, the creation date, right here before the file. I could do that with multiple files by selecting multipl files. I'll just use Shift Click to do that. I can Control click on any one of them. They're all still selected and I could say Rename File With Creation Date. Now you can see it's got all of them renamed using the creation date for each file as the first part of the file name.
Let's go back and say we don't want to use the creation date of the file. Why? Well, you often do this when you're dealing with photos. But what you really want is the date the photo was taken. But the creation date of the file may not match that. Stored in the metadata for jpeg images is the creation date for the file. We can actually look at that here. We can select one of these files. I can double click it and open it up in Preview. Then I can do Command i to get information on the file. You click on i here for metadata information and exif, that's the metadata that contains what we want and we can see here that we've got the date and all sorts of other information for this file.
We know we've got that stored in the file itself. Now can we get it in Terminal. We can using something called MDLS. MD stands for metadata and LS for listing. So we can get that here. Let's look at the data for that file by simply using mdls and then the name of the file. We're going to get all this information here. So we want to look carefully through all this to find the correct piece of metadata. So we find one here that's Content Creation Date. So that's probably what we want. So we want to note that.
Now we can do a command to just get that one line. We can use grep to do that. So this one line here will do the same thing we did before. mdls and the file name and it's going to use this pipe here, that basically says type it into this new command. This new command is going to be grep and it's going to say return the line with this piece of text on it. So hit Return. We actually get two lines. So what we really want is just the very first time it appears. So we'll modify the line with -m 1 which will give us just the first occurrence. So good. So now we have the date as part of the line. What we'd really like to do is just get that date by itself.
You can use awk to actually get that. This is the third word. That's the first word, second word, third word of that. So we're going to pipe it again through awk and then the command there in quotes is print out the third word. So we do that and you can see you get just the date portion. Perfect. That's what we want.
So now we can use this in a very similar Automator Quick Action. Here's the new Quick Action. Actually it looks very similar to the previous one. Does everything the same except here. We have filedate equals and then we have this shell script here. It's going to call it mdls for the file to get all the information. It's going to grep to get that one line here and then it's going to use awk to get the third part of that which is the date. It's going to send that to filedate. Then it's going to get the filename and the filepath like our previous script. Rename the file just like before. Except now instead of using the creation date for the file it's going to use the photo date from the metadata for that file.
So here we only want it to receive image files. Not files and folders because this will only work with images. It needs this metadata in there. So I'll save this and this is going to be Rename Photo File with Date. So now here in Pictures I can select one. Do Control and click and then Quick Actions and then select Rename File With Date and it will do what we want except now I get the actual date the photo was taken. In this case 2004. I can select all of these and Control click on them and do the same thing. Quick Actions and then Rename Photo File With Date. It will put the actual dates of each of those photos at the beginning of the file name for each one.
So you can modify this in many ways. For instance you can include more things in the date format like hours, minutes, and seconds. You can customize the file names even further using these shell scripts as a starting point.
Shell script for renaming by file date:
for f in "$@" do filedate=$(date -r $(stat -f %B $f) +%Y-%m-%d); filename=$f:t filepath=$f:h mv $filepath/{"$filename","$filedate $filename"} done
Shell script for renaming by photo metadata date:
for f in "$@" do filedate=$(mdls $f | grep kMDItemContentCreationDate -m 1 | awk '{print $3}'); filename=$f:t filepath=$f:h mv $filepath/{"$filename","$filedate $filename"} done
Felt obligated to comment since this is just the kind of content I enjoy. Someday I'll be looking for a way to get a photo's taken date into a script and I now have a solution. Thanks, Gary.
Excellent tip; I've just renamed more than 6,000 photos I couldn't organize by year without this. I tripped over trying to type in the terminal work before discovering I only needed to copy/paste your Automator Script. A+
Fantastic solution, Gary, and you have managed to introduce these complex concepts in an easily-understandable way. Thank you!
How can I modify the shell script to have the filedate but not including the original filename as the output.
In other words, I would like to original file to be renamed as: 12-27-1995.jpg
Dan: Instead of the renaming going to "$filedate $filename" just have it as "$filedate.jpg"
When I run it the name moves one space to the right and stops.
It works on external discs. I have a personal cloud Drive that it is not working on must be some kind of permission problem. Thanks for the info.
Thanks Gary, this is exactly what I've been looking for. A couple of questions though.
i) I can't work out how to concatenate the date and the time with an underscore separating the two.
ii) The date seems to be returned as a UTC value, not what is in the EXIF info
iii) Rather than having colons as a separator between the hours minutes and seconds, forward slashes (/) are substituted
iv) How can I remove the separators in both the date and time fields?
Many thanks.
I'm getting spaces like Al was. When I do mdls on a file directly by dropping it into terminal, there are only 15 constants displayed as null or empty and no kMDItemContentCreationDate listed. I'm running Mojave and suspect t his may be a Catalina only command.
Very useful! Can't wait to try it! Thanks Gary.
Peter: That's going to take some string processing in your script. It is all possible, but only if you take the time to learn some more programming. Alternatively, you could use a regular batch rename in the Finder to do things like replace spaces with _. UTC is probably what is really in the EXIF info, you just see a converted value in Preview. I'm thinking there is probably a way to convert the string date in the shell script too, but it will take more research.
Good video Gary. Can you do this inside the Photos App?
Gene: No. You can't even set the file name of a photo manually inside the Photos app.
This is nice and a great explanation. Can Automator be used to stuff the 'real' date of a photo into the metadata field for the date the picture was taken? I've scanned pictures and they have a created/modified date in 2019 but I would like to identify them with the real point in time for which the picture was taken (i.e., our wedding date.)
Dennis: Possibly. But it will get a lot more complex. A Google search came up with some things, but I haven't investigated them.
Congratulations Gary, this is what I've been looking for since apple abandoned Aperture. (In Aperture, there was a sophisticated renaming tool for files upon import).