Skip to content

Commit e69ae43

Browse files
Implement 'wc' command alternative for counting lines, words, and bytes in files
1 parent 97b42cb commit e69ae43

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

  • implement-shell-tools/wc

implement-shell-tools/wc/wc.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import argparse
2+
import locale
3+
4+
5+
#set locale to the machine default setting
6+
locale.setlocale(locale.LC_ALL, '')
7+
8+
parser = argparse.ArgumentParser(
9+
prog="wc",
10+
description="An alternative to the 'wc' command",
11+
)
12+
parser.add_argument("files", nargs="+", help="The file(s) to process")
13+
parser.add_argument("-l", "--lines", action="store_true", help="Print the newline counts")
14+
parser.add_argument("-w", "--words", action="store_true", help="Print the word counts")
15+
parser.add_argument("-c", "--bytes", action="store_true", help="Print the byte counts")
16+
17+
args = parser.parse_args()
18+
19+
# when no specific flags are set
20+
no_flags = not (args.lines or args.words or args.bytes)
21+
22+
totals = {"lines": 0, "words": 0, "bytes": 0}
23+
24+
def calculate_counts(content):
25+
# returns a count object
26+
return {
27+
"lines": content.count('\n') + (1 if content and not content.endswith('\n') else 0),
28+
"words": len(content.split()),
29+
"bytes": len(content.encode('utf-8')),
30+
}
31+
32+
33+
def print_counts(counts, file):
34+
parts = []
35+
# map flag args to the keys in the count object
36+
flag_arg_to_key = {
37+
"lines": args.lines,
38+
"words": args.words,
39+
"bytes": args.bytes
40+
}
41+
42+
PADDING = 3
43+
44+
for key, flag in flag_arg_to_key.items():
45+
if no_flags or flag:
46+
# apply padding only when no_flags is True
47+
padded_output = f"{counts[key]:>{PADDING}}" if no_flags else str(counts[key])
48+
parts.append(padded_output)
49+
parts.append(file)
50+
print(" ".join(parts))
51+
52+
53+
for file in args.files:
54+
try:
55+
with open(file, "r") as f:
56+
# read the content and split the lines ready to process as needed
57+
content = f.read()
58+
counts = calculate_counts(content)
59+
# update totals object with values from count object
60+
for key in totals:
61+
totals[key] += counts[key]
62+
print_counts(counts, file)
63+
except FileNotFoundError:
64+
print(f"wc: {file}: No such file or directory found")
65+
66+
# Print totals if more than one file
67+
if len(args.files) > 1:
68+
print_counts(totals, "total")

0 commit comments

Comments
 (0)