Skip to content

Commit 5476f45

Browse files
refactored and corrected code to meet and answer the asked questions for all the files
1 parent fcac82c commit 5476f45

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

implement-shell-tools/cat/cat.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import glob
21
import argparse
32
from enum import Enum
43

@@ -7,23 +6,27 @@ class Numbering(Enum):
76
ALL = 1
87
NONEMPTY = 2
98

10-
def cat(filepath, numbering=Numbering.NONE, line_counter=None):
9+
def print_numbered_line(line, line_number, pad=6):
10+
print(f"{line_number:{pad}}\t{line}", end='')
11+
return line_number + 1
12+
13+
def cat(filepath, numbering, start_line):
14+
line_number = start_line
1115
try:
1216
with open(filepath) as f:
1317
for line in f:
1418
if numbering == Numbering.NONEMPTY:
1519
if line.strip():
16-
print(f"{line_counter[0]:6}\t{line}", end='')
17-
line_counter[0] += 1
20+
line_number = print_numbered_line(line, line_number)
1821
else:
1922
print(line, end='')
2023
elif numbering == Numbering.ALL:
21-
print(f"{line_counter[0]:6}\t{line}", end='')
22-
line_counter[0] += 1
24+
line_number = print_numbered_line(line, line_number)
2325
else:
2426
print(line, end='')
2527
except FileNotFoundError:
2628
print(f"cat: {filepath}: No such file or directory")
29+
return line_number
2730

2831
def main():
2932
parser = argparse.ArgumentParser(description="Concatenate files and print on the standard output.")
@@ -32,13 +35,6 @@ def main():
3235
parser.add_argument('files', nargs='+', help='files to concatenate')
3336
args = parser.parse_args()
3437

35-
files = []
36-
for pattern in args.files:
37-
files.extend(glob.glob(pattern) or [pattern])
38-
39-
line_counter = [1]
40-
41-
# Determine numbering mode (mutually exclusive)
4238
if args.n and args.b:
4339
parser.error("options -n and -b are mutually exclusive")
4440
elif args.n:
@@ -48,8 +44,9 @@ def main():
4844
else:
4945
numbering = Numbering.NONE
5046

51-
for file in sorted(files):
52-
cat(file, numbering=numbering, line_counter=line_counter)
47+
line_number = 1 # start line numbering
48+
for file in args.files:
49+
line_number = cat(file, numbering=numbering, start_line=line_number)
5350

5451
if __name__ == "__main__":
5552
main()

implement-shell-tools/ls/ls.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import os
22
import argparse
33

4-
def ls(path='.', one_column=False, show_hidden=False):
4+
def ls(path, one_column, show_hidden):
5+
"""List files in a directory, optionally in one column or including hidden files."""
56
try:
67
files = os.listdir(path)
78
if not show_hidden:
@@ -14,6 +15,8 @@ def ls(path='.', one_column=False, show_hidden=False):
1415
print(*files)
1516
except FileNotFoundError:
1617
print(f"ls: cannot access '{path}': No such file or directory")
18+
except NotADirectoryError:
19+
print(f"ls: cannot access '{path}': Not a directory")
1720

1821
def main():
1922
parser = argparse.ArgumentParser()
@@ -25,4 +28,4 @@ def main():
2528
ls(args.path, args.one_column, args.a)
2629

2730
if __name__ == "__main__":
28-
main()
31+
main()

implement-shell-tools/wc/wc.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
import argparse
22

33
def wc(path, count_lines, count_words, count_bytes):
4+
"""Count lines, words, and bytes for a single file."""
45
try:
56
with open(path, 'r') as f:
67
content = f.read()
78
lines = content.splitlines()
89
words = content.split()
910
bytes_ = len(content.encode('utf-8'))
1011

12+
# Determine what to show
13+
if not any([count_lines, count_words, count_bytes]):
14+
count_lines = count_words = count_bytes = True
15+
1116
parts = []
1217
if count_lines: parts.append(str(len(lines)))
1318
if count_words: parts.append(str(len(words)))
1419
if count_bytes: parts.append(str(bytes_))
1520

16-
if not parts:
17-
parts = [str(len(lines)), str(len(words)), str(bytes_)]
1821
print(' '.join(parts), path)
1922

23+
return (len(lines) if count_lines else 0,
24+
len(words) if count_words else 0,
25+
bytes_ if count_bytes else 0)
2026
except FileNotFoundError:
2127
print(f"wc: {path}: No such file or directory")
28+
return (0, 0, 0)
2229
except IsADirectoryError:
2330
print(f"wc: {path}: Is a directory")
31+
return (0, 0, 0)
2432

2533
def main():
2634
parser = argparse.ArgumentParser()
@@ -30,8 +38,21 @@ def main():
3038
parser.add_argument('paths', nargs='+', help='Files to count')
3139
args = parser.parse_args()
3240

41+
total_lines = total_words = total_bytes = 0
42+
multiple_files = len(args.paths) > 1
43+
3344
for path in args.paths:
34-
wc(path, args.l, args.w, args.c)
45+
l, w, b = wc(path, args.l, args.w, args.c)
46+
total_lines += l
47+
total_words += w
48+
total_bytes += b
49+
50+
if multiple_files:
51+
parts = []
52+
if args.l or not any([args.l, args.w, args.c]): parts.append(str(total_lines))
53+
if args.w or not any([args.l, args.w, args.c]): parts.append(str(total_words))
54+
if args.c or not any([args.l, args.w, args.c]): parts.append(str(total_bytes))
55+
print(' '.join(parts), 'total')
3556

3657
if __name__ == "__main__":
37-
main()
58+
main()

0 commit comments

Comments
 (0)