index all rss twitter github linkedin email

Álvaro Ramírez

05 December 2018 Diffing directories content size

Needed to diff two directories, but only interested in file size changes. diff, find, sort, and stat seem to do the job:

diff <(find dir1 -type f -exec stat -f '%N %z' '{}' \; | sort) <(find dir2 -type f -exec stat -f '%N %z' '{}' \; | sort)
1,3c1,2
< dir1/one.txt 14
< dir1/subdir/file.txt 5
< dir1/three.txt 7
---
> dir2/one.txt 19
> dir2/two.txt 0

Note: Using diff, find, sort, and stat on macOS.

Update 1

I've since learned about mtree (thanks Roman!). A nice utility to add to the toolbox.

mtree -p emacs-25.1 -c -k size -d
#	   user: me
#	machine: my-machine
#	   tree: /path/to/emacs-25.1
#	   date: Wed Dec  5 22:21:07 2018
# .
/set type=dir
.               size=1152
# ./admin
admin           size=960
# ./admin/charsets
charsets        size=544
# ./admin/charsets/glibc
glibc           size=3392
# ./admin/charsets/glibc
..
# ./admin/charsets/mapfiles
mapfiles        size=640
# ./admin/charsets/mapfiles
..

Update 2

I've added Emacs ediff to the mix:

(require 'f)

(defun ar/ediff-dir-content-size ()
    "Diff all subdirectories (sizes only) in two directories."
    (interactive)
    (let* ((dir1-path (read-directory-name "Dir 1: "))
           (dir2-path (read-directory-name "Dir 2: "))
           (buf1 (get-buffer-create (format "*Dir 1 (%s)*" (f-base dir1-path))))
           (buf2 (get-buffer-create (format "*Dir 2 (%s)*" (f-base dir2-path)))))
      (with-current-buffer buf1
        (erase-buffer))
      (with-current-buffer buf2
        (erase-buffer))
      (shell-command (format "cd %s; find . -type d | sort | du -h" dir1-path) buf1)
      (shell-command (format "cd %s; find . -type d | sort | du -h" dir2-path) buf2)
      (ediff-buffers buf1 buf2)))

ediff-dir-content-size.png