Readable source
#!/usr/bin/env python3
"""Write an asset inventory to stdout with relative names, sizes, MIME types and hashes."""
import argparse,json,hashlib,mimetypes,struct
from pathlib import Path
def inspect(path,root):
h=hashlib.sha256()
with path.open('rb') as f:
header=f.read(24);h.update(header)
for chunk in iter(lambda:f.read(1024*1024),b''):h.update(chunk)
item={'path':str(path.relative_to(root)),'bytes':path.stat().st_size,'mime':mimetypes.guess_type(path.name)[0] or 'application/octet-stream','sha256':h.hexdigest()}
if len(header)==24 and header[:8]==b'\x89PNG\r\n\x1a\n':item['width'],item['height']=struct.unpack('>II',header[16:24])
return item
def main():
p=argparse.ArgumentParser(description=__doc__);p.add_argument('folder',type=Path);a=p.parse_args()
if not a.folder.is_dir():p.error('Folder does not exist.')
root=a.folder.resolve();files=[];errors=[]
for path in sorted(root.rglob('*')):
if path.is_file() and not path.is_symlink():
try:files.append(inspect(path,root))
except OSError as e:errors.append({'path':str(path),'error':str(e)})
print(json.dumps({'root_name':root.name,'count':len(files),'total_bytes':sum(f['bytes'] for f in files),'files':files,'errors':errors},indent=2))
if __name__=='__main__':main()