0

I've got image files scattered all around my computer so I'd like to write a script that receives as input a full path to a directory, display the total size of image (.jpg , .jpeg) files in each of the subdirectories and sum up all the gathered sizes and display the sum as well . Any ideas ?

2
  • Dimensions or filesize?
    – Oli
    Jan 17, 2015 at 9:24
  • filesize, sorry
    – user43389
    Jan 17, 2015 at 9:24

2 Answers 2

1

The following isn't perfect. It doesn't handle directories with spaces well but unless you have a load of header directories with identical suffixes, that's not really an issue.

find -type f -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -printf '%h %s\n' \
| awk -F '[ /]' '{a[$2] += $NF} END{for(i in a){print i, a[i]}}'
4
  • Why not a regex for the extension list? This will quickly become unwieldy.
    – muru
    Jan 17, 2015 at 9:56
  • 1
    I don't think it will; we're only looking for images and I've already covered all the major food groups there. Regex searches are slower (takes about twice as long here). But yeah, something like -iregex '.*\(jpe?g\|png\|gif\)$' does work.
    – Oli
    Jan 17, 2015 at 9:59
  • I'm hopeless with scripting, but I've got a question..I was interested in a script that got a path as input and displays recursively the filesize of image files withing each subdirectory then prints the sum at the end..I don't really get how yours script works and how does it get its input path..
    – user43389
    Jan 17, 2015 at 10:04
  • This works off the current path. You can specify a path as the first argument of find (eg find /path/to/dir/ -type f ...).
    – Oli
    Jan 17, 2015 at 10:10
1

Definitely more verbose, a python option:

#!/usr/bin/env python3
import subprocess
import os
#---------------------------
directory = '/path/to/images'
m_subject = 'image'
#---------------------------
def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

total_size = []
for root, dirs, files in os.walk(directory):
    for file in files:
        file = '"'+root+'/'+file+'"' 
        mtype = get('file --mime-type '+file).strip().split(' ')[-1]
        if m_subject in mtype:
            size = get("du -hk "+file).split()[0]; total_size.append(int(size))
            print(file.strip('"')+"\n", mtype+"\n", size+" k\n")
print("-"*30, "\nnumber of files: "+str(len(total_size)), "\ntotal size: "+str(sum(total_size))+" k")
try:
    print("average size: "+str(int(sum(total_size)/len(total_size)))+" k")
except ZeroDivisionError:
    pass

It lists all image files recursively inside directory, gives the size per file and the total size in the end:

..................

/path/to/image3828.JPG
 image/jpeg
 1024 k

/path/to/image3829.JPG
 image/jpeg
 1024 k

/path/to/image3830.JPG
 image/jpeg
 1024 k

------------------------------
number of files: 3830
total size: 4248576 k
average size: 1109 k

How to use:

  • Copy the script into an empty file
  • In the head section of the script, set the type (m_subject =) and the directory (directory =) you'd like to be searched.
  • Save it as list_image.py
  • Run it by the command:

    python3 /path/to/list_image.py
    

Refining results

You can further limit the found results by changing the valuem_subject = to image/jpeg or image/pngfor example.


Edit: sorting options

You didn't ask for it, but now we have the script, it would be a pity not to add a few more (sorting) options, to get a better insight on the occurrence of images inside your directory.

The version below adds the option to sort by "size", "name", "directory" or "type". Sorted by "size", giving an output like:

.........

image_09.jpg            image/jpeg  956 k   /path/to/image_1.jpg
image_10.jpg            image/jpeg  1044 k  /path/to/image_2.jpg
image_11.jpg            image/jpeg  1072 k  /path/to/image_3.jpg
image_12.jpg            image/jpeg  1108 k  /path/to/image_4.jpg
image_13.jpg            image/jpeg  1180 k  /path/to/image_5.jpg
image_14.jpg            image/jpeg  1720 k  /path/to/image_6.jpg
image_15.jpg            image/jpeg  1832 k  /path/to/image_7.jpg
------------------------------ 
number of files: 15 
total size: 13160 k
average size: 877 k

The script

  • Use it like explained for the first option.
#!/usr/bin/env python3
import subprocess
import os
#---------------------------
directory = '/path/to/images'
m_subject = 'image'
sort = "size" # options are: "size", "name", "directory", "type"
#---------------------------
def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

total_size = []
images = []
# gathering information on the images
for root, dirs, files in os.walk(directory):
    for file in files:
        file_dr = '"'+root+'/'+file+'"' 
        mtype = get('file --mime-type '+file_dr).strip().split(' ')[-1]
        if m_subject in mtype:
            size = get("du -hk "+file_dr).split()[0]; total_size.append(int(size))
            images.append([file, mtype, int(size), file_dr.replace('"', "")])
# sorting options
if sort == "name":
    images.sort(key=lambda x: x[0])
elif sort == "type":
    images.sort(key=lambda x: x[1])
elif sort == "size":
    images.sort(key=lambda x: x[2])
elif sort == "directory":
    images.sort(key=lambda x: x[3])
for image in images:
    image[2] = str(image[2])+" k"
# print info per image
    print(("\t").join(image))
#print summary
print("-"*30, "\nnumber of files: "+str(len(total_size)), "\ntotal size: "+str(sum(total_size))+" k")
try:
    print("average size: "+str(int(sum(total_size)/len(total_size)))+" k")
except ZeroDivisionError:
    pass
1
  • @user43389 did you manage somehow? Jan 18, 2015 at 17:26

You must log in to answer this question.

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