Skip to content

Commit 0e07af9

Browse files
committed
implemented shell tools (cat, ls, wc) in python
1 parent 4ef88e2 commit 0e07af9

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"githubPullRequests.ignoredPullRequestBranches": [
3+
"main"
4+
]
5+
}

implement-shell-tools/cat/cat.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
4+
# implement-shell-tools/cat/cat.py
5+
def main():
6+
parser = argparse.ArgumentParser(
7+
prog="cat",
8+
description="Implements a simple version of the 'cat' command to read and display file contents."
9+
)
10+
11+
parser.add_argument("-n", help="Number lines", action="store_true")
12+
parser.add_argument("-b", help="Number non-blank lines", action="store_true")
13+
parser.add_argument("path", nargs="+", help="The file to search")
14+
15+
args = parser.parse_args()
16+
17+
for file_path in args.path:
18+
try:
19+
with open(file_path, 'r') as file:
20+
content = file.read()
21+
lines = content.split("\n")
22+
line_number = 1
23+
non_blank_line_number = 1
24+
25+
for i, line in enumerate(lines):
26+
if i == len(lines) - 1 and line == "": # Skip the last empty line if it exists
27+
break
28+
prefix = ""
29+
if args.n:
30+
prefix = str(line_number).rjust(6) + " "
31+
elif args.b and line != "":
32+
prefix = str(non_blank_line_number).rjust(6) + " "
33+
print(prefix + line)
34+
line_number += 1
35+
if line != "":
36+
non_blank_line_number += 1
37+
38+
except FileNotFoundError:
39+
print(f"cat: {file_path}: No such file or directory")
40+
except Exception as e:
41+
print(f"cat: {file_path}: {e}")
42+
43+
if __name__ == "__main__":
44+
main()

implement-shell-tools/ls/ls.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import argparse
2+
import os
3+
4+
# implement-shell-tools/ls/ls.py
5+
def main():
6+
parser = argparse.ArgumentParser(
7+
prog="ls",
8+
description="Implements a simple version of the 'ls' command to list files in a directory."
9+
)
10+
11+
parser.add_argument("-1", help="", action="store_true")
12+
parser.add_argument("-a", help="", action="store_true")
13+
parser.add_argument("directory", nargs="?", default=".", help="The directory to search")
14+
15+
args = parser.parse_args()
16+
17+
try:
18+
files = os.listdir(args.directory)
19+
20+
if not args.a:
21+
files = [f for f in files if not f.startswith(".")]
22+
23+
files = sorted(files)
24+
25+
for f in files:
26+
print(f)
27+
28+
except FileNotFoundError:
29+
print(f"ls: {args.directory}: No such file or directory")
30+
except NotADirectoryError:
31+
print(args.directory)
32+
except Exception as e:
33+
print(f"ls: {args.directory}: {e}")
34+
35+
if __name__ == "__main__":
36+
main()

implement-shell-tools/wc/wc.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import argparse
2+
import sys
3+
4+
# implement-shell-tools/wc/wc.py
5+
def wc_file(path):
6+
"""Return (lines, words, bytes) for a given file."""
7+
with open(path, "r", encoding="utf-8") as f:
8+
text = f.read()
9+
lines = text.count("\n")
10+
words = len(text.split())
11+
chars = len(text.encode("utf-8")) # byte count
12+
return lines, words, chars
13+
14+
15+
def main():
16+
parser = argparse.ArgumentParser(
17+
prog="wc",
18+
description="Implements a simple version of the 'wc' command to count lines, words, and characters in text files."
19+
)
20+
21+
parser.add_argument("-l", action="store_true", help="Count lines")
22+
parser.add_argument("-w", action="store_true", help="Count words")
23+
parser.add_argument("-c", action="store_true", help="Count characters")
24+
parser.add_argument("path", nargs="+", help="The files to read")
25+
26+
args = parser.parse_args()
27+
28+
if not (args.l or args.w or args.c):
29+
args.l = args.w = args.c = True # Default to all counts if none specified
30+
31+
total_lines = total_words = total_chars = 0
32+
33+
for file_path in args.path:
34+
try:
35+
lines, words, chars = wc_file(file_path)
36+
total_lines += lines
37+
total_words += words
38+
total_chars += chars
39+
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))
49+
50+
except FileNotFoundError:
51+
print(f"wc: {file_path}: No such file or directory", file=sys.stderr)
52+
except Exception as e:
53+
print(f"wc: {file_path}: {e}", file=sys.stderr)
54+
55+
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))
65+
66+
if __name__ == "__main__":
67+
main()

0 commit comments

Comments
 (0)