The little things give you away... A collection of various small helper stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

79 lines
1.8 KiB

  1. #!/usr/bin/env python3
  2. # Read file sizes from stdin, print sum on stdout
  3. # Accepted formats on stdin:
  4. # - '1.2 MB', interpreted as 1200000 bytes
  5. # - '1.2 MiB', interpreted as 1.20 * 1024 * 1024 = 1258291.2 bytes
  6. # - '1.2M', interpreted as MiB
  7. # - '123', interpreted as 123 bytes
  8. # Known units: B; kB, MB, GB, TB, PB, EB; KiB, MiB, GiB, TiB, PiB, EiB; K, M, G, T, P, E
  9. # In all cases, whitespace is optional, can be any width, and may contain tabs. Leading and trailing whitespace is also permitted.
  10. # All numbers are cast to an integer before summation.
  11. # Output is by default formatted as IEC (i.e. KiB, MiB, etc.).
  12. import math
  13. import re
  14. import sys
  15. units = {
  16. 'B': 1,
  17. # SI prefixes
  18. 'kB': 1000,
  19. 'MB': 1000**2,
  20. 'GB': 1000**3,
  21. 'TB': 1000**4,
  22. 'PB': 1000**5,
  23. 'EB': 1000**6,
  24. # IEC
  25. 'KiB': 1024,
  26. 'MiB': 1024**2,
  27. 'GiB': 1024**3,
  28. 'TiB': 1024**4,
  29. 'PiB': 1024**5,
  30. 'EiB': 1024**6,
  31. # Short IEC
  32. 'K': 1024,
  33. 'M': 1024**2,
  34. 'G': 1024**3,
  35. 'T': 1024**4,
  36. 'P': 1024**5,
  37. 'E': 1024**6,
  38. }
  39. sum = 0
  40. for line in sys.stdin:
  41. origLine = line.rstrip('\r\n')
  42. line = re.sub(r'\s+', '', line.strip())
  43. line = re.sub(r'([a-zA-Z])', r' \1', line, count = 1)
  44. if ' ' in line:
  45. number, unit = line.split(' ', 1)
  46. else:
  47. number = line
  48. unit = 'B'
  49. if unit not in units:
  50. print(f'Skipping line with unknown unit: {origLine}', file = sys.stderr)
  51. continue
  52. try:
  53. if number.strip('0123456789') == '':
  54. number = int(number)
  55. else:
  56. number = float(number)
  57. except ValueError as e:
  58. print(f'Skipping line with unparseable number: {origLine}', file = sys.stderr)
  59. continue
  60. sum += int(number * units[unit])
  61. # Special case because log(0) is kinda bad...
  62. if sum == 0:
  63. print('0 B')
  64. sys.exit(0)
  65. log = int(math.log(sum if sum > 0 else -sum, 1024))
  66. unit = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'][log]
  67. if unit == 'B':
  68. print(f'{sum} {unit}')
  69. else:
  70. print(f'{sum / 1024**log :.2f} {unit}')