-
-
Notifications
You must be signed in to change notification settings - Fork 42
London | SDC-Nov-25 | Pezhman Azizi | Sprint 4 | Implement shell Tools In Python #299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| import sys | ||
| import argparse | ||
|
|
||
| # Create the argument parser – similar style to `count-containing-words` | ||
| parser = argparse.ArgumentParser( | ||
| prog="cat", | ||
| description="Prints the contents of one or more files", | ||
| ) | ||
|
|
||
| # positional argument: one or more paths | ||
| parser.add_argument( | ||
| "paths", | ||
| nargs="+", | ||
| help="The file(s) to print", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| # Loop over each path and print its content | ||
| for path in args.paths: | ||
| try: | ||
| with open(path, "r", encoding="utf-8") as f: | ||
| for line in f: | ||
| # print line exactly as it appears in the file | ||
| sys.stdout.write(line) | ||
| except FileNotFoundError: | ||
| # match shell cat-style error message | ||
| sys.stderr.write(f"cat: {path}: No such file or directory\n") |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good neat script! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| import os | ||
| import sys | ||
| import argparse | ||
|
|
||
| parser = argparse.ArgumentParser( | ||
| prog="ls", | ||
| description="Simple reimplementation of ls", | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-1", | ||
| dest="one_per_line", | ||
| action="store_true", | ||
| help="List one entry per line", | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-a", | ||
| dest="all_files", | ||
| action="store_true", | ||
| help="Do not ignore entries starting with .", | ||
| ) | ||
|
|
||
| # Optional path (default = current directory) | ||
| parser.add_argument( | ||
| "path", | ||
| nargs="?", | ||
| default=".", | ||
| help="Directory to list (default: current directory)", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| # Get all items in the directory | ||
| try: | ||
| entries = os.listdir(args.path) | ||
| except FileNotFoundError: | ||
| sys.stderr.write(f"ls: cannot access '{args.path}': No such file or directory\n") | ||
| sys.exit(1) | ||
|
|
||
| # Handle -a (hidden files) | ||
| if not args.all_files: | ||
| entries = [e for e in entries if not e.startswith(".")] | ||
|
|
||
| # Sort for stable behaviour | ||
| entries.sort() | ||
|
|
||
| # Output: -1 = one per line | ||
| if args.one_per_line: | ||
| for entry in entries: | ||
| print(entry) | ||
| else: | ||
| # default: space-separated | ||
| print(" ".join(entries)) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| import argparse | ||
| import sys | ||
| import os | ||
|
|
||
| parser = argparse.ArgumentParser( | ||
| prog="wc", | ||
| description="Simple reimplementation of wc" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-l", | ||
| dest="count_lines", | ||
| action="store_true", | ||
| help="Print the line counts" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-w", | ||
| dest="count_words", | ||
| action="store_true", | ||
| help="Print the word counts" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-c", | ||
| dest="count_bytes", | ||
| action="store_true", | ||
| help="Print the byte counts" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "paths", | ||
| nargs="+", | ||
| help="File(s) to process" | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
|
|
||
| def wc_file(path): | ||
| """Return (lines, words, bytes) for a file.""" | ||
| try: | ||
| with open(path, "r", encoding="utf-8") as f: | ||
| content = f.read() | ||
| except FileNotFoundError: | ||
| sys.stderr.write(f"wc: {path}: No such file or directory\n") | ||
| return None | ||
|
|
||
| lines = content.count("\n") + (1 if content and not content.endswith("\n") else 0) | ||
| words = len(content.split()) | ||
| bytes_ = len(content.encode("utf-8")) | ||
|
|
||
| return lines, words, bytes_ | ||
|
|
||
|
|
||
| # If no flags are supplied, show all three | ||
| show_all = not (args.count_lines or args.count_words or args.count_bytes) | ||
|
|
||
| totals = [0, 0, 0] # lines, words, bytes | ||
| multiple_files = len(args.paths) > 1 | ||
|
|
||
| for path in args.paths: | ||
| result = wc_file(path) | ||
| if result is None: | ||
| continue | ||
|
|
||
| lines, words, bytes_ = result | ||
|
|
||
| totals[0] += lines | ||
| totals[1] += words | ||
| totals[2] += bytes_ | ||
|
|
||
| output_parts = [] | ||
|
|
||
| if show_all: | ||
| output_parts.extend([str(lines), str(words), str(bytes_)]) | ||
| else: | ||
| if args.count_lines: | ||
| output_parts.append(str(lines)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When multiple files are given, does the output look neat enough? is there any way you could improve how it looks? |
||
| if args.count_words: | ||
| output_parts.append(str(words)) | ||
| if args.count_bytes: | ||
| output_parts.append(str(bytes_)) | ||
|
|
||
| output_parts.append(path) | ||
| print(" ".join(output_parts)) | ||
|
|
||
|
|
||
| # If multiple files → print total line | ||
| if multiple_files: | ||
| totals_output = [] | ||
|
|
||
| if show_all: | ||
| totals_output.extend([str(totals[0]), str(totals[1]), str(totals[2])]) | ||
| else: | ||
| if args.count_lines: | ||
| totals_output.append(str(totals[0])) | ||
| if args.count_words: | ||
| totals_output.append(str(totals[1])) | ||
| if args.count_bytes: | ||
| totals_output.append(str(totals[2])) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you see the repetition in the structure of the output part of the script? can you think of any way to improve this? |
||
|
|
||
| totals_output.append("total") | ||
| print(" ".join(totals_output)) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script works well, but you may want to take another look at the readme for this task, you seem to be missing some features