Skip to content

Commit 3770801

Browse files
committed
amended cat.py, ls.py, and wc.py
1 parent 0e07af9 commit 3770801

File tree

3 files changed

+63
-34
lines changed

3 files changed

+63
-34
lines changed

implement-shell-tools/cat/cat.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ def main():
1414

1515
args = parser.parse_args()
1616

17+
line_number = 1
18+
non_blank_line_number = 1
19+
1720
for file_path in args.path:
1821
try:
1922
with open(file_path, 'r') as file:
2023
content = file.read()
2124
lines = content.split("\n")
22-
line_number = 1
23-
non_blank_line_number = 1
2425

2526
for i, line in enumerate(lines):
2627
if i == len(lines) - 1 and line == "": # Skip the last empty line if it exists

implement-shell-tools/ls/ls.py

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,66 @@
1+
# implement-shell-tools/ls/ls.py
12
import argparse
23
import os
4+
import sys
5+
import shutil
6+
import math
7+
8+
def print_columns(items, force_single_column=False):
9+
"""Print items in columns unless -1 is passed or output is not a tty."""
10+
if force_single_column or not sys.stdout.isatty():
11+
for item in items:
12+
print(item)
13+
return
14+
15+
# Get terminal width
16+
term_width = shutil.get_terminal_size((80, 20)).columns
17+
18+
if not items:
19+
return
20+
21+
# Longest filename length + spacing
22+
max_len = max(len(f) for f in items) + 2
23+
cols = max(1, term_width // max_len)
24+
rows = math.ceil(len(items) / cols)
25+
26+
for r in range(rows):
27+
row_items = []
28+
for c in range(cols):
29+
i = c * rows + r
30+
if i < len(items):
31+
row_items.append(items[i].ljust(max_len))
32+
print("".join(row_items).rstrip())
333

4-
# implement-shell-tools/ls/ls.py
534
def main():
635
parser = argparse.ArgumentParser(
736
prog="ls",
837
description="Implements a simple version of the 'ls' command to list files in a directory."
938
)
1039

11-
parser.add_argument("-1", help="", action="store_true")
12-
parser.add_argument("-a", help="", action="store_true")
40+
parser.add_argument("-1", help="List one file per line", action="store_true")
41+
parser.add_argument("-a", help="Include hidden files", action="store_true")
1342
parser.add_argument("directory", nargs="?", default=".", help="The directory to search")
1443

1544
args = parser.parse_args()
1645

1746
try:
18-
files = os.listdir(args.directory)
47+
if os.path.isdir(args.directory):
48+
files = os.listdir(args.directory)
1949

20-
if not args.a:
21-
files = [f for f in files if not f.startswith(".")]
22-
23-
files = sorted(files)
50+
if not args.a:
51+
files = [f for f in files if not f.startswith(".")]
52+
53+
files = sorted(files)
2454

25-
for f in files:
26-
print(f)
55+
print_columns(files, force_single_column=args.__dict__["1"])
56+
else:
57+
# If it's a file, just print the name
58+
print(args.directory)
2759

2860
except FileNotFoundError:
29-
print(f"ls: {args.directory}: No such file or directory")
30-
except NotADirectoryError:
31-
print(args.directory)
61+
print(f"ls: {args.directory}: No such file or directory", file=sys.stderr)
3262
except Exception as e:
33-
print(f"ls: {args.directory}: {e}")
63+
print(f"ls: {args.directory}: {e}", file=sys.stderr)
3464

3565
if __name__ == "__main__":
3666
main()

implement-shell-tools/wc/wc.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,24 @@ def wc_file(path):
77
with open(path, "r", encoding="utf-8") as f:
88
text = f.read()
99
lines = text.count("\n")
10+
if text and not text.endswith("\n"):
11+
lines += 1 # Count last line if it doesn't end with newline
1012
words = len(text.split())
1113
chars = len(text.encode("utf-8")) # byte count
1214
return lines, words, chars
1315

16+
def format_counts(lines, words, chars, args, label):
17+
"""Return formatted output string for wc counts."""
18+
parts = []
19+
if args.l:
20+
parts.append(str(lines).rjust(8))
21+
if args.w:
22+
parts.append(str(words).rjust(8))
23+
if args.c:
24+
parts.append(str(chars).rjust(8))
25+
if label:
26+
parts.append(label)
27+
return " ".join(parts)
1428

1529
def main():
1630
parser = argparse.ArgumentParser(
@@ -37,31 +51,15 @@ def main():
3751
total_words += words
3852
total_chars += chars
3953

40-
counts = []
41-
if args.l:
42-
counts.append(str(lines))
43-
if args.w:
44-
counts.append(str(words))
45-
if args.c:
46-
counts.append(str(chars))
47-
counts.append(file_path)
48-
print(" ".join(counts))
54+
print(format_counts(lines, words, chars, args, file_path))
4955

5056
except FileNotFoundError:
5157
print(f"wc: {file_path}: No such file or directory", file=sys.stderr)
5258
except Exception as e:
5359
print(f"wc: {file_path}: {e}", file=sys.stderr)
5460

5561
if len(args.path) > 1:
56-
counts = []
57-
if args.l:
58-
counts.append(str(total_lines))
59-
if args.w:
60-
counts.append(str(total_words))
61-
if args.c:
62-
counts.append(str(total_chars))
63-
counts.append("total")
64-
print(" ".join(counts))
62+
print(format_counts(total_lines, total_words, total_chars, args, "total"))
6563

6664
if __name__ == "__main__":
6765
main()

0 commit comments

Comments
 (0)