Print to file image sizes

I was trying to figure out how to write a shell script to be able to print the name of the file and size to a text file I wanted to know if I was on the right track and am understanding this better.

In my script a for loop be able to print files over 4mb (we charge differently for larger images)

image="/Home/Desktop/images"

(cd "$image" 
 for f in *.jpg; do
   let fsize=$(stat -c %s "$f")
   if (( fsize == 4mb )); then
     echo "$f"
   fi
 done) > mnt/desktop/sizes/results.txt

my understanding:
check variable $image that is being set from the directory
f is all images from *
do f's size and make a variable inside $()
stat -c %s prints the file name?
if condition is met for fsize equals 4mb size
print variable $f
to file results.txt

Slight changes to your script:

image="/Home/Desktop/images"

{
 cd "$image"
 for f in *.jpg
 do
  let fsize=$(stat -c %s "$f")
  if (( fsize > 4194304 ))
  then
   echo "$f"
  fi
 done
} > mnt/desktop/sizes/results.txt

am I on the right track and understanding this??

EDIT:
how do you come up with the size amount?? example if I have a 2mb file what would it be in Linux?

That'll be 2*1024*1024=2097152 bytes. stat -c %s file also returns the size in bytes.

for got the ; after fsize

I extended my code to check the directory but now my issue is if try to echo $f it gives me the full path and the filename of the image. How can I just get the name to also print next to the directory??

		echo 'checking images sizes'
		{
			
			for f in $(find $DIRECTORY/$directoryname -name \*.jpg);
				do
				let fsize=$(stat -c %s "$f");
					if (( fsize > 2097152 ))
						then
							echo "$directoryname  $f"
					fi
				done
			} >> results.txt

EDIT:
and how do you do an && in bash so I can check for .jpeg and .jpg

man find
You will see it supports logical OR and AND,
for example

find $DIRECTORY/$directoryname -name "*.jpg" -o -name "*.jpeg"
1 Like

so close but when I change that line to that I get

find: invalid esxpression; you have used a binary operator '-0' with nothing before it.

EDIT:
ok I see where it talks about it thanks!!

Now my issue is when I echo the variable $f I get path/path/path/path/name. How can I just echo name??

---------- Post updated 10-31-12 at 09:11 AM ---------- Previous update was 10-30-12 at 05:39 PM ----------

still stuck when I try to echo variable f it gives me the full path and not just the name.

Show your code.

thanks just finally got it after 24 hours. I needed basename

final script example:

echo 'checking images sizes'
		{
			for f in $(find $DIRECTORY/$directoryname -name "*.jpg" -o -name "*.jpeg");
				do
				let fsize=$(stat -c %s "$f");
					if (( fsize > 2097152 ))
						then
                                                       images=$(basename $f)
                                                        echo "The following images need reviewing"
							echo "Location: $directoryname"
                                                        echo "Images: $images"
					fi
				done
			} >> results.doc

EDIT:
I was trying to figure out how to sed or use --xpath before echo "the following" and access an .xml file that has a tag <name></name> but Im still stuck there and if I can figure out the way to pull data from xml files it would really help me out.

Show the XML file.

Im trying to get a tag <name></name> that never changes

If you say so.

echo "abcdef<name>asdf</name>qwerty" | awk 'match($0,"<name>[^<]*</name>") { print substr($0, RSTART+6, RLENGTH-(6+7)); }'

asdf

$

If that doesn't work, you'll have to do as asked and post the XML, because a trivial answer often isn't good enough. XML can take many different forms.

even though im trying to pull data from a tag that doesnt change??

well i screwed up big time anyways its not 2mb its 2 million pixels so now I have to try and learn imageMagic

I really don't know.

Because you haven't shown the XML.

this is something like it

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<metadata>
    <name>John Does<name>
    <project>FIC042040</project>
    <class>FIC042030</class>
    <address>3232 Wellms</address>
    <city>Franklin</city>
    <state>TN</state>
    <filetype>Baker Group</filetype>
    <image>job12345.jpg</image>
    <jobstate>prepress</jobstate>
</metadata>

when I run name=$(grep -r "<name>.*</name>" $DIRECTORY .xml)

I get the result of

Name: path/path/path/filename.xml/<name>John Does</name>

I just need it to be result of
Name: John Does

This <name> will always be in the xml files but there are several lines and other elements into it that will change the location.

Thank you.

Time and time again people post simplified XML and complain when code doesn't work with their real data. I've learned to be picky.

The code I've given you ought to work. If the name had contained newlines or contained extra tag elements or anything like that, it wouldn't.

my apologies if Im being complicated Im still trying to learn and understand whats going on to help me better. Can you explain whats going on or tell me where I can learn what you did?

awk is a programming language found on any UNIX system handy for processing text files. It is handy like grep, powerful like sed, and has actual variables and statements, but not as unwieldy as perl. A full description of it would be out of scope here.

match() is a function that returns a positive number if the regular expression is found inside the line( i.e. $0 ). If it returns anything positive, then the code block following it inside { } is executed.

RSTART and RLENGTH are variables that tell where the string is found, match() sets them.

substr() is used to extract the string. substr($0, RSTART, RLENGTH) would extract the whole thing, just like egrep. Adding to RSTART and subtracting from RLENGTH excludes the tag portion.

Lastly, print prints. :slight_smile:

Here's an old post of mine if you want to explore awk more in depth.