Skip to content

Commit a676909

Browse files
committed
Python Implementation
1 parent e328bd5 commit a676909

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

implement-shell-tools/cat/mycat.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import argparse
2+
import glob
3+
4+
parser = argparse.ArgumentParser(
5+
prog="mycat",
6+
description="Outputs the content of the given file(s), like the cat command",
7+
)
8+
9+
parser.add_argument("-n", help="Number all lines", action="store_true")
10+
parser.add_argument("-b", help="Number all non-blank lines", action="store_true")
11+
parser.add_argument("path", help="The file to display(allowing wildcards)", nargs="+")
12+
13+
args = parser.parse_args()
14+
15+
file_list = []
16+
for path in args.path:
17+
file_list.extend(glob.glob(path))
18+
19+
line_number = 1
20+
21+
for filename in file_list:
22+
try:
23+
with open(filename, "r") as f:
24+
for line in f:
25+
stripped = line.rstrip("\n")
26+
27+
if args.b:
28+
if stripped:
29+
print(f"{line_number:>6}\t{stripped}")
30+
line_number += 1
31+
else:
32+
print("")
33+
elif args.n:
34+
print(f"{line_number:>6}\t{stripped}")
35+
line_number += 1
36+
else:
37+
print(line, end="")
38+
except FileNotFoundError:
39+
print(f"mycat: {filename}: No such file or directory")

implement-shell-tools/ls/myls.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import argparse
2+
import os
3+
4+
parser = argparse.ArgumentParser(
5+
prog="myls",
6+
description="List directory contents like the ls command"
7+
)
8+
9+
parser.add_argument("-1", dest="one_per_line", action="store_true",
10+
help="List one file per line")
11+
parser.add_argument("-a", dest="all_files", action="store_true",
12+
help="Include hidden files starting with '.'")
13+
parser.add_argument("path", nargs="?", default=".", help="Directory to list (default: current directory)")
14+
15+
args = parser.parse_args()
16+
17+
try:
18+
entries = os.listdir(args.path)
19+
except FileNotFoundError:
20+
print(f"my_ls: cannot access '{args.path}': No such file or directory")
21+
exit(1)
22+
23+
if not args.all_files:
24+
entries = [e for e in entries if not e.startswith('.')]
25+
26+
entries.sort()
27+
28+
if args.one_per_line:
29+
for entry in entries:
30+
print(entry)
31+
else:
32+
print(" ".join(entries))

implement-shell-tools/wc/mywc.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import argparse
2+
import glob
3+
import os
4+
5+
def count_file(file_path, count_lines=False, count_words=False, count_bytes=False):
6+
lines = words = bytes_count = 0
7+
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
8+
for line in f:
9+
lines += 1
10+
words += len(line.split())
11+
bytes_count = os.path.getsize(file_path)
12+
13+
if not (count_lines or count_words or count_bytes):
14+
return lines, words, bytes_count
15+
16+
return (
17+
lines if count_lines else None,
18+
words if count_words else None,
19+
bytes_count if count_bytes else None
20+
)
21+
22+
def main():
23+
parser = argparse.ArgumentParser(description="count lines, words, and bytes like the wc command")
24+
parser.add_argument("-l", action="store_true", help="Count lines")
25+
parser.add_argument("-w", action="store_true", help="Count words")
26+
parser.add_argument("-c", action="store_true", help="Count bytes")
27+
parser.add_argument("path", nargs="+", help="Files to count")
28+
29+
args = parser.parse_args()
30+
31+
total_lines = total_words = total_bytes = 0
32+
file_list = []
33+
for pattern in args.path:
34+
file_list.extend(glob.glob(pattern))
35+
36+
for file_path in file_list:
37+
counts = count_file(file_path, args.l, args.w, args.c)
38+
39+
if not (args.l or args.w or args.c):
40+
lines, words, bytes_count = counts
41+
print(f"{lines:>7} {words:>7} {bytes_count:>7} {file_path}")
42+
total_lines += lines
43+
total_words += words
44+
total_bytes += bytes_count
45+
else:
46+
count_strings = []
47+
if counts[0] is not None:
48+
count_strings.append(f"{counts[0]:>7}")
49+
total_lines += counts[0]
50+
if counts[1] is not None:
51+
count_strings.append(f"{counts[1]:>7}")
52+
total_words += counts[1]
53+
if counts[2] is not None:
54+
count_strings.append(f"{counts[2]:>7}")
55+
total_bytes += counts[2]
56+
print(" ".join(count_strings), file_path)
57+
58+
if len(file_list) > 1:
59+
if not (args.l or args.w or args.c):
60+
print(f"{total_lines:>7} {total_words:>7} {total_bytes:>7} total")
61+
else:
62+
total_strings = []
63+
if args.l:
64+
total_strings.append(f"{total_lines:>7}")
65+
if args.w:
66+
total_strings.append(f"{total_words:>7}")
67+
if args.c:
68+
total_strings.append(f"{total_bytes:>7}")
69+
print(" ".join(total_strings), "total")
70+
71+
if __name__ == "__main__":
72+
main()

0 commit comments

Comments
 (0)