ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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.
When annotating jpegs, whether newly-downloaded or on their way to being backed up to CDs/DVDs, I like to use the same 7 IPTC tags, and also on occasion Keywords and Supplemental Categories. Here's a list of the six:
Category
Credit
Source
Caption Writer
Transmission Reference
Fixture ID (also known as Event or Job ID) I use ObjectName as a 'clone' of this for GUI apps like IrfanView that don't "read" JobID in.
Location (IIM V.4 labels it "Sublocation")
Here's the script I have:
Code:
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for file in $(ls *.jpg);
do
echo
#9-point check:
cate=$(exiv2 -g Iptc.Application2.Category -Pv $file)
cred=$(exiv2 -g Iptc.Application2.Credit -Pv $file)
sour=$(exiv2 -g Iptc.Application2.Source -Pv $file)
writ=$(exiv2 -g Iptc.Application2.Writer -Pv $file)
trans=$(exiv2 -g Iptc.Application2.TransmissionReference -Pv $file)
fixid=$(exiv2 -g Iptc.Application2.FixtureId -Pv $file)
objnm=$(exiv2 -g Iptc.Application2.ObjectName -Pv $file)
locn=$(exiv2 -g Iptc.Application2.SubLocation -Pv $file)
keys0=$(exiv2 -g Iptc.Application2.Keywords -Pv $file)
cats0=$(exiv2 -g Iptc.Application2.SuppCategory -Pv $file)
#Now tell the people:
echo -e "File $file:"
echo -ne "$file: ">>favesmissing.txt
if [ -n "$cate" ]; then
echo -e "HAS a Category tag,"
else
echo -e "DOESN'T HAVE a Category tag,"
echo -ne " Category Tag">>favesmissing.txt
fi
if [ -n "$cred" ]; then
echo -e "HAS a Credit tag,"
else
echo -e "DOESN'T HAVE a Credit tag,"
echo -ne " Credit Tag">>favesmissing.txt
fi
if [ -n "$sour" ]; then
echo -e "HAS a Source tag,"
else
echo -e "DOESN'T HAVE a Source tag,"
echo -ne " Source Tag">>favesmissing.txt
fi
if [ -n "$writ" ]; then
echo -e "HAS a Caption Writer tag,"
else
echo -e "DOESN'T HAVE a Caption Writer tag,"
echo -ne " Writer Tag">>favesmissing.txt
fi
if [ -n "$trans" ]; then
echo -e "HAS a Transmission Reference tag,"
else
echo -e "DOESN'T HAVE a Transmission Reference tag,"
echo -ne " Transmission Reference Tag">>favesmissing.txt
fi
if [ -n "$fixid" ]; then
echo -e "HAS an Event/Fixture Identifier tag,"
else
echo -e "DOESN'T HAVE an Event/FixtureIdentifier tag,"
echo -ne " Fixture Id Tag">>favesmissing.txt
fi
if [ -n "$objnm" ]; then
echo -e "HAS an Object Name tag,"
else
echo -e "DOESN'T HAVE an Object Name tag,"
echo -ne " Object Name Tag">>favesmissing.txt
fi
if [ -n "$locn" ]; then
echo -e "HAS a Location tag,"
else
echo -e "DOESN'T HAVE a Location Name tag,"
echo -ne " Location Tag\n">>favesmissing.txt
fi
if [ -n "$keys0" ]; then
echo -e "HAS Keywords,"
echo -ne "Has Keywords">>favesmissing.txt
else
echo -e "DOESN'T HAVE Keywords,"
fi
if [ -n "$cats0" ]; then
echo -e "and HAS Supplemental Categories."
echo -ne " * Has Supp. Cats.\n">>favesmissing.txt
else
echo -e "but DOESN'T HAVE Supplemental Categories."
fi
done
IFS=$SAVEIFS
This much works splendidly in stdout.
The kind of Output I'm trying to avoid seeing (and having to edit in advance of processing with another script) looks lie this:
Code:
bh_07498_015.jpg: Has Keywordsbh_07710_007.jpg: Has Keywordsbh_07710_009.jpg:
bh_09035_016.jpg: bh_09035_018.jpg: bh_09071_004.jpg: bh_09071_006.jpg:
bh_09071_010.jpg: bh_09071_012.jpg: bh_7498_015.jpg:
bh_7710_04.jpg: bizarrepic2029.jpg: Has Keywords * Has Supp. Cats.
(the above output all to one line without breaks)
...and also the more-than-occasional ones of these:
Code:
1608.jpg: Fixture Id Tag Location Tag
Has Keywords * Has Supp. Cats.
I believe I'm looking at either a case/esac loop or a function, because in order (as I see the problem) for the script to Output discrete lines that begin with a filename and end with the last IPTC tag that's missing from file X.jpg,everything about the file must be known before dumping it all to the ASCII file. As I've never written either of the length and detail that are obviously required in this case, and because I'm almost sure "the longer they are, the more finely-tailored they have to be," I'm looking for assistance in writing 'long & involved' case/esacs or functions from people who've done asmuch.
I hope this provides enough information. Looking forward to considered replies.
BZT
Last edited by SilversleevesX; 08-23-2010 at 12:14 PM.
Same story as always, show us what you have tried and where you are getting stuck?
This seems to have been a mammoth task, but I do not seem to be seeing a lot of your input, but mainly questions.
Yes it is a question site but I believe the idea is to learn.
You have also been shown time and again that arrays will probably help if you are storing multiple values for the same file (ie jpg).
As far as case statements go, again show us your ideas and we can help or amend where you may make a mistake.
You wrote a script, don't like the output, so you want a second script to correct the output of the first one? Wouldn't it be better to do things right right of the beginning?
I don't understand, what are your desired results? What are undesired results? What further processing is intended (if there is any)?
What's wrong with
Quote:
Has Keywordsbh_07710_007.jpg
? The absence of a space character? grep doesn't stop this.
What's wrong with
Quote:
Has Keywords * Has Supp. Cats.
?
Let's talk about the basics.
As far as I see, you produce a 10-value-array, consisting of "exists/exists not", associated to a filename.
Quote:
bh_07498_015.jpg: Has Keywordsbh_07710_007.jpg: Has Keywordsbh_07710_009.jpg:
bh_09035_016.jpg: bh_09035_018.jpg: bh_09071_004.jpg: bh_09071_006.jpg:
bh_09071_010.jpg: bh_09071_012.jpg: bh_7498_015.jpg:
bh_7710_04.jpg: bizarrepic2029.jpg: Has Keywords * Has Supp. Cats.
This is really a ugly representation, seen from a programmers point of view!
You have also been shown time and again that arrays will probably help if you are storing multiple values for the same file (ie jpg).
As I see it, it was the "echo -ne" commands in the original script that were responsible for running the this tag is missing incidental phrases into the subsequent filenames. I wanted to avoid that, while at the same time keeping the output nice and "compact." Maybe bluebox's idea of using 1's and 0's is the best way to go about it.
Quote:
Originally Posted by grail
As far as case statements go, again show us your ideas and we can help or amend where you may make a mistake.
Rebuilt with case, getting a syntax error (unexpected token, ;; ) on this code:
Code:
#for file in $*.jpg; do
file="strangepic07.jpg"
case "$file" in
*.jpg )
cate=$(exiv2 -g Iptc.Application2.Category -Pv $file)
if [ -n $cate ]; then
cate1="HAS a Category Tag"
fi
cred=$(exiv2 -g Iptc.Application2.Credit -Pv $file)
if [ -n $cred ]; then
cred1="HAS a Credit Tag"
fi
sour=$(exiv2 -g Iptc.Application2.Source -Pv $file)
if [ -n $cred ]; then
sour1="HAS a Source Tag."
fi
writ=$(exiv2 -g Iptc.Application2.Writer -Pv $file)
if [ -n $writ ]; then
writ1="HAS a Caption Writer Tag"
fi
trans=$(exiv2 -g Iptc.Application2.TransmissionReference -Pv $file)
if [ -n $trans ]; then
trans1="HAS a Transmission Reference tag"
fi
fixid=$(exiv2 -g Iptc.Application2.FixtureId -Pv $file)
if [ -n $fixid ]; then
fixid1="Has an Event/Fixture Identifier Tag"
fi
objnm=$(exiv2 -g Iptc.Application2.ObjectName -Pv $file)
if [ -n $objnm ]; then
objnm1="HAS an Object Name/Title Tag"
fi
locn=$(exiv2 -g Iptc.Application2.SubLocation -Pv $file)
if [ -n $locn ]; then
locn1="HAS a Location Tag"
fi
keys0=$(exiv2 -g Iptc.Application2.Keywords -Pv $file)
if [ -n $keys0 ]; then
keys00="HAS Keywords"
else
keys00="does NOT have Keywords"
fi
cats0=$(exiv2 -g Iptc.Application2.SuppCategory -Pv $file)
if [ -n $cats0 -a -n $keys0 ]; then
cats00="and HAS Supplemental Categories."
else if [ -n $keys0 -a -z $cats0]; then
cats00="but does NOT have Supplemental Categories."
fi
;;
esac
echo -e "File $file:"
echo -ne "$cate1\n$cred1\n$sour1\n$writ1\n$trans\n$fixid\n$objnm1\n$locn1\n$keys00\n$cats00\n"
#done
NB:At this point, the furthest I've taken it from the original script, besides the case/esac loop, is what is seen in stdout. I don't have it writing anything to text yet.
I commented out the for/do/done to see if it would work on one specific file. Rather than write that filename to its own ASCII text file, I thought to set it to the variable file.
I suppose it's not kosher to have so many if/then/fi's inside a case/esac loop, but I've yet to puzzle out where else to put them. At any rate, rewriting it this way has given me some ideas on how to make the original script work the way I want it, in terms of "dumped" output.
BZT
Last edited by SilversleevesX; 08-23-2010 at 06:06 PM.
SilversleevesX, if all you want is a trailing newline after each tag list, your first script was completely okay. The only thing missing was:
Code:
fi
echo
# write a newline after each for-loop
# maybe add a echo >> favesmissing.txt
done
IFS=$SAVEIFS
Besides that, you should remove the newlines from " Location Tag\n" and " * Has Supp. Cats.\n" (except there is a special reason for it).
I don't see how a case structure could be useful for you. You have ten if-then-clauses and each has to be processed. "case" is useful if you have ten if-then-clauses but only one "case" has to be processed.
In case we talk about tighten your code, think about this pseudocode:
Code:
for file in $(ls *.jpg);
do
line=$file" ";
for i in "Category Credit Source Writer TransmissionReference FixtureId ObjectName SubLocation Keywords SuppCategory"; do
if [ -n `exiv2 -g Iptc.Application2.$i -Pv $file` ]; then
line=$line" "${i}" Tag is not missing "
else
line=$line" "${i}" Tag is missing "
fi
done;
echo $line;
done
This is written out of my head, untested and will most likely not work out of the shelf!
There a two nested for-loops. The outer one goes through all your files listed by "ls". The inner one goes through your ten if-then clauses, reducing your code.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.