Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hallo to everybody, I searched a lot in the net but I wasn't able to paste correctly the information I found.
I have a dir with a lot of jpg files; many of them have quite similar subjects (2 teacher visiting a museum with their students); I'd like to create a movie (I'll use Kdenlive) but I need to order them properly before.
I thought to use imagemagik tools:
Code:
identify -format %[EXIF:datetimeoriginal] a.jpg
I've created a file, called lista, containing all the files name.
If I try
Code:
for i in `cat lista`; do indentify -format %[EXIF:dateTimeOriginal] $i; done
my terminal gives me the correct list with all the date and time of creation.
I'd like to join this info to with the original filename.
I tried
Code:
origdir="../Foto Museo 16-04-13/"
destdir="./"
for i in `cat lista`; do cp "$origdir$i" "$destdir`identify -format %[EXIF:dateTimeOriginal] $i`$i"; done
but I obtained a simple copy of all the files from $origdir to $destdir with the original name.
I've tried a bash script too
Code:
#!/bin/bash
origdir="../Foto\ museo\ 16-04-13"
destdir="./"
for i in `cat lista` do
datascatto=`identify -format %[EXIF:dateTimeOriginal] $origdir$i`
echo cp "$origdir$i" "$destdir$datascatto$i"
done
I tried to translate the Italian error but I'm not sure if I used the correct terms.
Are you talking about the Italian word "inatteso"? If that was the Italian original then "unexpected" is a better translation. "Unattented" means rather "incustodito" when speaking of luggage.
Ciao,
jdk
The do in your for loop must either be preceeded by a semicolon (;) or on on a separate line.
I've correct the error; thanks for the input
Quote:
Are you talking about the Italian word "inatteso"? If that was the Italian original then "unexpected" is a better translation. "Unattented" means rather "incustodito" when speaking of luggage.
Ciao,
jdk
You're right. Wrong translation.
Unfortunately the script is not yet doing the right renaming: I continue to find non renamed files.
I'll search for this opion, I started with for loop because I know its structure. :-)
Quote:
Use either backslashes or quotes. Not both. I recommend quotes:
Code:
#origdir="../Foto\ museo\ 16-04-13"
origdir="../Foto museo 16-04-13"
You're right, I'm sorry, I've corrected it in the Code section I used directly from the CLI but not in the script; in anycase I've used only the quotes.
Quote:
Instead of reading from a file, I'd just loop over the files and grab the data directly. You can use a for loop for that.
Code:
#!/bin/bash
origdir="../Foto museo 16-04-13"
destdir="./"
for fname in "$origdir/"*; do
datascatto=$( identify -format '%[EXIF:dateTimeOriginal]' "$fname" )
echo cp -t "destdir" "$datascatto${fname##*/}"
done
I used the file to work on selected files only.
Quote:
I also seem to remember that imagemagick has some rather advanced file naming features built in, BTW. You might check the online site documentation.
I red the documentation but I didn't find what i need, sorry, I'll try to read more carefully again.
Dear Sirs, first of all thanks for all your replies.
David, I've not yet iplemented the While loop, I've no time to read carefully the documentation but I'll do asap.
In any case I changed a bit my script, and now it does what I want.
Here the new release.
Code:
#!/bin/bash
for i in `cat lista`; do
datascatto=`identify -format %[EXIF:dateTimeOriginal] $i|awk '{print $2}'|sed -e 's/:/-/g'`
cp $i "$datascatto"_$i
done
Now I start from a file called
IMG_4381.jpg
and I arrive at the end with another file called
10-43-58_IMG_4381.jpg
Because the photo was taken on 16th of April at 10:43:58a.m.
LISTFILE=lista
while read -r line
do
EXIFINFO=$(identify -format %[EXIF:dateTimeOriginal] ${line} | sed -e 's/[ :]*/-/g')
NEWFILE=$(dirname ${line})/${EXIFINFO}_$(basename ${line})
cp ${line} ${NEWFILE}
done < $LISTFILE
Why did I use basename? If your list happens to have a path name included with the filename (such as "Photos/April16/IMG_4381.jpg"), the resulting name as you had it will be a bad filename ("10-43-58_Photos/April16/IMG_4381.jpg"). I use dirname and basename to fix that (now you'll get "Photos/April16/10-43-58_IMG_4381.jpg"). You can remove the dirname part if you want it copied to the current directory (the directory the script is being run in) along with the rest:
Code:
NEWFILE=${EXIFINFO}_$(basename ${line})
Also, the braces around the variable names prevents bash from including characters you do not want interpreted as part of the variable name from doing so. This is preferred to your quotes around "$datascatto" in the cp command above.
There's some basic error checking you can do as well, such as rejecting files with invalid EXIF data (such as none, or malformed file names).
If you want to operate on only certain files, it depends on what criteria you need to select them by.
If it's a simple name pattern and you don't need to work recursively, you can usually use a globbing pattern to select them. Bash also has an extra extended globbing system for added selective power.
(From version 4 there's also a new "**" globstar pattern that can be used to do recursive matching. Unfortunately it will currently lock up your shell session if it there are any recursive directory symlinks, so use it with caution.)
For more advanced matching, you probably need to use find, in which case you have to use a while loop with null delimiters (or often you can use its built-in -exec option instead of a shell loop).
You should also use the while loop if you have a file. Again, never use cat like that.
Once a string is in a variable, built-in shell string manipulations is usually better to use instead of external substitution commands (this includes basename, the pattern for which I demonstrated in my last post).
(Even when you do use external commands, a single sed or awk command can cover any number of lower-powered tools. You should almost never need chains of commands like "grep | sed | awk". Learn how to use your tools!)
Brackets around variables are only needed with parameter substitution, and if you have to separate the variable name from other characters that could be mistaken for it. Variable names can include letters, numbers, and the underscore. Otherwise they just clutter up the code and make it easier for errors to slip in. If you don't need it, leave it out.
And to repeat again, don't use backticks for command substitution. "$(..)" is the recommended pattern now.
Finally, QUOTE ALL OF YOUR VARIABLE EXPANSIONS. You should never leave the quotes off a parameter expansion unless you explicitly want the resulting string to be word-split by the shell and any possible globbing patterns expanded. This is a vitally important concept in scripting, so train yourself to do it correctly now. You can learn about the exceptions when you need them.
goumba's version above is pretty much what you should be using, except for the unecessary basename and lack of safe quoting.
Code:
#!/bin/bash
listfile=lista
destdir='./'
while read -r fname; do
etime=$( identify -format '%[EXIF:dateTimeOriginal]' "$line" )
etime=${etime#* } #remove everything up to the first space
etime=${etime//:/-} #replace colons with hyphens in the part that remains
newname=${etime}_${fname##*/} #remove the path from the original filename
# while building the final output file
cp "$fname" "$destdir/$newname"
done < "$listfile"
If you want to process, for example, all .jpg files in the original directory, then glob it like this instead:
Code:
#!/bin/bash
origdir="../Foto museo 16-04-13"
destdir="./"
for fname in "$origdir/"*.jpg; do
...< as above > ...
done
Last edited by David the H.; 05-15-2013 at 02:12 PM.
Reason: small corrections
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.