1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
#!/usr/bin/env python3
from pathlib import Path
import functools
import operator
import os.path
import stat
import sys
BLOCK_SIZES = (
(1024 * 1024 * 1024 * 1024, "T"),
(1024 * 1024 * 1024, "G"),
(1024 * 1024, "M"),
(1024, "K"),
)
def format_size(size):
for bs, unit in BLOCK_SIZES:
if size >= bs:
return "%.1f%s" % (size / bs, unit)
return str(size)
def tree(path, dirs_only=False, max_depth=0, _depth=0):
path = Path(path)
lst = path.lstat()
is_symlink = stat.S_ISLNK(lst.st_mode)
st = lst if is_symlink else path.stat()
is_dir = stat.S_ISDIR(st.st_mode)
if is_symlink:
size = 0
elif is_dir:
size = functools.reduce(
operator.add,
[
tree(p, dirs_only=dirs_only, max_depth=max_depth, _depth=_depth + 1)
for p in sorted(path.iterdir())
],
0,
)
else:
size = lst.st_size
if (is_dir or not dirs_only) and (not max_depth or _depth <= max_depth):
p = str(path)
if is_dir:
p += os.path.sep
if is_symlink:
p += " -> " + os.readlink(str(path))
print("%10s %s" % (format_size(size), p))
return size
def main():
args = []
max_depth = 0
dirs_only = False
argv = iter(sys.argv[1:])
for a in argv:
if a == "-d":
dirs_only = True
continue
if a == "-L":
max_depth = int(next(argv))
continue
if a.startswith("-"):
raise ValueError(a)
args.append(a)
for a in args:
tree(a, dirs_only=dirs_only, max_depth=max_depth)
if __name__ == "__main__":
main()
|