I have files that are named like "12. 2017-04-11 063118.jpg", and "123. 2016-09-05 115236.jpg". The number to the left of the "." counts up like an index from 1 to 1400.

How can I set the creation date and time according to how it is specified in the file name for all 1400 files I have in the folder. I know the command touch -t changes the creation date, but I do not know how to extract the date/time information from the file name and put this into a command so this is done automatically for all files.

I know from another thread that the below should work. but i don't know how to tweak the text conversion to correctly apply to my file naming convention.

for f in *; do
    t=$(echo $f | sed -E 's/([A-z]*-)|([ ,;])|(\..*)//g' | sed -E 's/(.*)(..)/\1.\2/')
    touch -t $t "$f"

The above code works if my file naming convention is like "clip-2014-01-31 18;50;15.mp4", however, I have a different format: "12. 2017-04-11 063118.jpg", and "123. 2016-09-05 115236.jpg". Does anyone know how to tweak the sed function command to process the conversion into the correct format for touch?

3 Answers 3


Bash parameter expansion will work:

for f in *; do
    t="${f#* }"
    touch -t $t "$f"
  • t="${f#* }" strips off the part before (< the first space)
  • t="${t%%.*}" strips off the part after .
  • t="${t:0:4}${t:5:2}${t:8:2}${t:11:2}${t:13:2}.${t:15:2}" formats the content of the date variable (t) for touch which requires the following format: [[CC]YY]MMDDhhmm[.SS].

And as one-liner:

for f in *; do t="${f#* }"; t="${t%%.*}"; t="${t:0:4}${t:5:2}${t:8:2}${t:11:2}${t:13:2}.${t:15:2}"; touch -t $t "$f"; done
  • The bare *(glob) will list every file system object in the directory. Do you think that using *.jpg would be a better choice?
    – fd0
    Commented May 8, 2017 at 13:45
  • @fd0 The solution will only work for the given format something_without_spaces YYYY[.|-|:]MM[.|-|:]DD hhmmSS.someextension. It won't change the creation date if the required format CCYYMMDDhhmm.SS is wrong though (e.g. contains letters or if the dot is missing).
    – klanomath
    Commented May 8, 2017 at 13:58

Since you asked how you could tweak what you already had, you'd change the capture groups in the first occurrence of sed to match the new pattern, while leaving the second sed as is. Also double quote the $f in echo "$f" |.

Note however, I've eliminated the use of the pipe and second occurrence of sed, | sed ..., by use of the -e option, which appends the editing commands into a list of commands.

for f in *; do
    t=$(echo "$f" | sed -E -e 's/(.*\. )|([-])|([ ])|(\..*)//g' -e 's/(.*)(..)/\1.\2/')
    touch -t $t "$f"

Here it is tweaked as a one-liner:

for f in *; do t=$(echo "$f" | sed -E -e 's/(.*\. )|([-])|([ ])|(\..*)//g' -e 's/(.*)(..)/\1.\2/'); touch -t $t "$f"; done

Here's an explication of the capture groups in the first sed editing command:

enter image description here

Which leaves you with 20160905115236 and when processed by the second sed editing command, it becomes 201609051152.36 as (.*)(..) breaks it down to two capture groups, the second containing the last two characters and the first containing everything else. The . gets placed in the substitution portion having back-referenced /\1.\2/ both capture groups.


If the files contain exit tags, the free 'exiftool' can change the file name according to values within the file. Installing it also installs a detailed man page.


I have used this tool to not only change file names, but to write HTML snippets to show the files on a web page.

  • OK, my bad. Reading it again, I see you want to change the file dates, not the name. It may be that exiftool can do that. My MAC is not working, so I can't read the man page.
    – WGroleau
    Commented May 6, 2017 at 3:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .