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 Answers
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]}}'
-
Why not a regex for the extension list? This will quickly become unwieldy.– muruJan 17, 2015 at 9:56
-
1I 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.. Jan 17, 2015 at 10:04
-
This works off the current path. You can specify a path as the first argument of
find
(egfind /path/to/dir/ -type f ...
).– Oli ♦Jan 17, 2015 at 10:10
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/png
for 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