LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 09-03-2006, 01:36 PM   #1
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Rep: Reputation: 15
Rename file based on its own date/time stamp


I would like to batch rename a bunch of files in a directory based on each file's individual date/time stamp. Basically, I get *.avi files off my camera that I want renamed to their date/time of origin (file date/time). The camera names them sequentially.

jhead works great for *.jpg files, but won't work for non-jpg files. mv won't look at the date/time stamp of the file.

I'm sure it is an easy thing to do, if I could just find the right command-line utility...

Any ideas?
 
Old 09-03-2006, 02:17 PM   #2
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
Create a file named 'date_rename.sh' with the following content:
Code:
#!/bin/bash
place="${1:-.}"
find "$place" -type f -iname "*.avi" -printf "%T+ %p\n" | while read ts f; do
  d="$(dirname "$f")"
  f="$(basename "$f")"
  e="${f##*.}"
  s=
  if [ -e "$d/$ts.$e" ] || [ -e "$d/$ts_00.$e" ]; then
    [ -e "$d/$ts_00.$e" ] || mv "$d/$ts.$e" "$d/$ts_00.$e"
    s=01
    while [ -e "$d/$ts_$s.$e" ]; do s=$(awk '{printf "%02u", $1+1}' <<<"$s"); done
    s=_$s
  fi
  mv "$d/$f" "$d/$ts$s.$e"
done
Run with:
./date_rename.sh /path/to/directory/with/avi/inside
I did not test so try with fake data first.

Yves.

Last edited by theYinYeti; 09-03-2006 at 02:37 PM.
 
Old 09-03-2006, 02:25 PM   #3
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Original Poster
Rep: Reputation: 15
Wow! Seems like there should be a simpler more elegant way. I couldn't be the first one who wants to do such a thing, and that's a whole lot of bash scripting for such a simple job...

Did you just write this? Or have you used it before?
 
Old 09-03-2006, 02:33 PM   #4
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
This is not complicated at all. Here's what it does:
- find files named "something.avi", whatever the case (AVI, avi, aVi...) and ask the "find" command to output the date+time, and the filename with path.
- for each date+time, and full path:
1/ get dirname, filename, and extension, along with an empty ssuffix.
2/ check if the name that we'll use is not already used, and if so rename the existing file with suffix "_00", and from there start an incremental naming: 01, 02, 03... (should be rare if not impossible, unless you mix photos from different cameras)
3/ do the actual renaming from the old name to the new one (timestamp + suffix (may be empty) + extension)

As for your question, I indeed wrote it just now, because I'm too lazy to go and fetch the one I wrote for my own usage.
By the way, I just see 1 error, which I'll correct just now in the original post.
...
Done.

As the script is saved in a file, you won't have to type it each time. So it is not different than using any command-line tool.

Yves.

Last edited by theYinYeti; 09-03-2006 at 02:40 PM.
 
1 members found this post helpful.
Old 09-03-2006, 03:38 PM   #5
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
Well, I did tests, and good that I did.
Here is the final version of the script with no errors:
Code:
#!/bin/bash
place="${1:-.}"
ext="${2:-avi}"
files="$(find "$place" -type f -iname "*.$ext" -printf "%T+ %p\n")"
while read ts f; do
  d="$(dirname "$f")"
  f="$(basename "$f")"
  e="${f##*.}"
  s=
  if [ -e "$d/$ts.$e" ] || [ -e "$d/${ts}_00.$e" ]; then
    [ -e "$d/${ts}_00.$e" ] || mv "$d/$ts.$e" "$d/${ts}_00.$e"
    s=01
    while [ -e "$d/${ts}_$s.$e" ]; do
      s=$(awk '{printf "%02u", $1+1}' <<<"$s");
    done
    s=_$s
  fi
echo "D: $d - F: $f - E: $e - S: $s => $d/$f -> $d/$ts$s.$e"
  mv "$d/$f" "$d/$ts$s.$e"
done <<<"$files"
I had forgotten some braces...
Besides, now you can choose the extension:

./date_rename.sh /some/dir
will rename inside the directory AVI files.

./date_rename.sh /some/dir mov
will rename inside the directory MOV files.

This time it is tested to some degree. Try with test files, though; it is always safer

Yves.

[edit:]The "echo" command at the end is purely optional (you can remove it). I used it for debug purposes, but I left it there as it tells you what it is doing.[/edit]

Last edited by theYinYeti; 09-04-2006 at 04:14 AM.
 
1 members found this post helpful.
Old 09-03-2006, 03:38 PM   #6
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
Well, I did tests, and good that I did.
Here is the final version of the script with no errors:
Code:
#!/bin/bash
place="${1:-.}"
ext="${2:-avi}"
files="$(find "$place" -type f -iname "*.$ext" -printf "%T+ %p\n")"
while read ts f; do
  d="$(dirname "$f")"
  f="$(basename "$f")"
  e="${f##*.}"
  s=
  if [ -e "$d/$ts.$e" ] || [ -e "$d/${ts}_00.$e" ]; then
    [ -e "$d/${ts}_00.$e" ] || mv "$d/$ts.$e" "$d/${ts}_00.$e"
    s=01
    while [ -e "$d/${ts}_$s.$e" ]; do
      s=$(awk '{printf "%02u", $1+1}' <<<"$s");
    done
    s=_$s
  fi
echo "D: $d - F: $f - E: $e - S: $s => $d/$f -> $d/$ts$s.$e"
  mv "$d/$f" "$d/$ts$s.$e"
done <<<"$files"
I had forgotten some braces...
Besides, now you can choose the extension:

./date_rename.sh /some/dir
will rename inside the directory AVI files.

./date_rename.sh /some/dir mov
will rename inside the directory MOV files.

This time it is tested to some degree. Try with test files, though; it is always safer

Yves.

[edit:]The "echo" command at the end is purely optional (you can remove it). I used it for debug purposes, but I left it there as it tells you what it is doing.[/edit]

Last edited by theYinYeti; 09-04-2006 at 04:14 AM.
 
1 members found this post helpful.
Old 09-03-2006, 04:56 PM   #7
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Original Poster
Rep: Reputation: 15
Thanks for the time that you put into this script. I wish I had your bash skills. :-)
 
Old 09-03-2006, 07:17 PM   #8
Sonneteer
Member
 
Registered: May 2006
Location: Canada
Distribution: Slackware 13.37; Ubuntu 12.04
Posts: 81
Blog Entries: 5

Rep: Reputation: 15
If you can get a hold of and use krename, it does wonders with batch renaming, including date/time functionality.

EDIT: Sorry, I somehow missed that you were looking for a command-line utility. Never mind me then.

Last edited by Sonneteer; 09-03-2006 at 11:34 PM.
 
Old 09-03-2006, 07:52 PM   #9
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Using find version 4.1.7 for me capital t in find's printf doesn't work.
This would move all files as "mv ./uniquefilename.avi ./%+.avi".
 
Old 09-03-2006, 10:08 PM   #10
Tinkster
Moderator
 
Registered: Apr 2002
Location: earth
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
Blog Entries: 11

Rep: Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928
You mean like so?
Code:
find  -type f -name "*avi" -printf "mv %h/%f %h/%TY%Tm%Td-%TH%TM%TS.avi\n"|sh
[edit]
Tested - didn't need the xargs
[/edit]


Cheers,
Tink

Last edited by Tinkster; 09-03-2006 at 10:23 PM.
 
Old 09-04-2006, 03:48 AM   #11
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
@Tinkster:

This is a clever idea. However, you'll have to refine it if spaces are allowed in the involved paths or file names, or if several files may happen to be created at the same second.

@unSpawn:

You're using a non-GNU or too-old version of find. You'll have to replace '%T+' with '%TY-%Tm-%Td+%TH:%TM:%TS' or any alternative you like.

Yves.
 
Old 09-04-2006, 04:12 AM   #12
Tinkster
Moderator
 
Registered: Apr 2002
Location: earth
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
Blog Entries: 11

Rep: Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928
Quote:
Originally Posted by theYinYeti
@Tinkster:

This is a clever idea. However, you'll have to refine it if spaces are allowed in the involved paths or file names, or if several files may happen to be created at the same second.
It's actually spawnys :} ... I just happened to type it having seen
what he intended to do ;}

Code:
find  -type f -name "*avi" -printf "mv \"%h/%f\" \"%h/%TY%Tm%Td-%TH%TM%Ts.avi\"\n"
should take care of both issues.



Cheers,
Tink

Last edited by Tinkster; 09-04-2006 at 04:14 AM.
 
Old 09-04-2006, 05:40 AM   #13
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
It's actually spawnys :}
No, can't take credit for that: never intended to solve it that way.
So it actually is your own idea :-] And a neat one at that.
 
Old 09-04-2006, 12:23 PM   #14
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Original Poster
Rep: Reputation: 15
A one-line bash solution. I like it. Thanks for the good bash work!
 
Old 09-04-2006, 12:46 PM   #15
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Original Poster
Rep: Reputation: 15
OK, now I'm having a problem getting the above bash command to do the desired task. The following command...

Code:
find -type f -name '*avi' -printf "mv -i "%h/%f" "%h/%TY%Tm%Td-%TH%TM%TS.avi"\n"
...produces the following output.

Code:
mv -i ./a.avi ./20060904-112549.avi
mv -i ./b.avi ./20060904-112551.avi
mv -i ./c.avi ./20060904-112552.avi
mv -i ./d.avi ./20060904-112554.avi
mv -i ./e.avi ./20060904-112556.avi
mv -i ./f.avi ./20060904-112558.avi
mv -i ./g.avi ./20060904-112600.avi
To execute the commands, I place the statements in an eval command...

Code:
eval `find -type f -name '*avi' -printf "mv -i "%h/%f" "%h/%TY%Tm%Td-%TH%TM%TS.avi"\n"`
But I get the following error:

Code:
mv: target `./20060904-112600.avi' is not a directory
What gives?
 
Old 09-04-2006, 12:56 PM   #16
airman99
LQ Newbie
 
Registered: Aug 2004
Distribution: Gentoo
Posts: 26

Original Poster
Rep: Reputation: 15

Never mind, I'll just pipe it to another shell instance as was demonstrated above.

Thanks again for the great solution.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
time stamp for file modification youngstorm Linux - Newbie 2 11-01-2005 03:46 PM
Rename file with date stamp MacSob Linux - General 6 09-13-2005 01:30 PM
search based on time stamp ? massai Linux - Newbie 1 03-07-2004 02:50 PM
Time stamp in Samba is 11 hours behind time stamp in Linux Linh Linux - General 3 09-04-2003 12:44 PM
auto file rename based on time wx_jason Linux - Newbie 10 07-10-2003 11:14 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 04:53 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration