-
-
Notifications
You must be signed in to change notification settings - Fork 42
London | SDC-Nov-2025 | Ikenna Agulobi | Sprint 4 | Implement shell tools python #301
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,50 @@ | ||
| import argparse | ||
| # ------------------------------------------- | ||
|
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. It's ok to have comments, but it would be even better to have the code split into methods with descriptive names :) |
||
| # Set up the argument parser | ||
| # ------------------------------------------- | ||
|
|
||
| parser = argparse.ArgumentParser( | ||
| prog ="display-file-content", | ||
| description = "Implement cat command with -n and -b flag support", | ||
| ) | ||
|
|
||
| parser.add_argument("-n", "--number-all-lines", | ||
| action="store_true", | ||
| help="Number every line in the file" | ||
| ) | ||
|
|
||
| parser.add_argument("-b", "--number-non-empty-lines", | ||
| action="store_true", | ||
| help="Number non empty lines in the file" | ||
| ) | ||
|
|
||
| parser.add_argument("paths", nargs="+", help="File paths to process") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| # ------------------------------------------- | ||
| # Implement functionality | ||
| # ------------------------------------------- | ||
|
|
||
| line_number = 1 | ||
|
|
||
| for filepath in args.paths: | ||
| with open(filepath, "r", encoding="utf-8") as f: | ||
| content = f.read() | ||
|
|
||
| lines = content.split("\n") | ||
|
Comment on lines
+33
to
+35
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. Maybe check if you could use |
||
|
|
||
| for line in lines: | ||
| if args.number_all_lines: | ||
| print(f"{line_number} {line}") | ||
| line_number += 1 | ||
|
|
||
| elif args.number_non_empty_lines: | ||
| if line.strip() == "": | ||
| print(line) | ||
| else: | ||
| print(f"{line_number} {line}") | ||
| line_number +=1 | ||
|
|
||
| else: | ||
| print(line) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| import argparse | ||
| import os | ||
| import sys | ||
|
|
||
|
|
||
| # Set up the argument parser | ||
| def parse_args(): | ||
| parser = argparse.ArgumentParser( | ||
| prog="list_files_in_directory", | ||
| description="Implement ls commands to list files in directory" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-1","--file-per-line", | ||
| action="store_true", | ||
| dest="file_per_line", | ||
| help="list files one per line" | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "-a", | ||
| "--files-and-hidden-ones", | ||
| action="store_true", | ||
| dest="files_and_hidden_ones", | ||
| help="list all files including hidden ones", | ||
| ) | ||
|
|
||
| parser.add_argument( | ||
| "paths", | ||
| nargs="*", | ||
| help="directories to list" | ||
| ) | ||
|
|
||
| return parser.parse_args() | ||
|
|
||
| # if no paths, default to current directory | ||
| def get_paths(args): | ||
| if len(args.paths) == 0: | ||
| return ["."] | ||
| return args.paths | ||
|
|
||
| # list a single directory | ||
| def list_directory(directory_path, show_hidden, file_per_line): | ||
|
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. It is good as is, but as a suggestion - a tiny bit cleaner approach would be to first get the list of directories/files and for list_directory function to just accept this list and print it (filtering whatever is not needed). This would follow 1 method/1 responsibility paradigm (which helps with code readability / reusability). |
||
| try: | ||
| entries = os.listdir(directory_path) | ||
| except OSError as err: | ||
| print(f"ls: cannot access '{directory_path}': {err}", file=sys.stderr) | ||
| return | ||
|
|
||
| if not show_hidden: | ||
| entries = [name for name in entries if not name.startswith(".")] | ||
|
|
||
| if file_per_line: | ||
| for name in entries: | ||
| print(name) | ||
| else: | ||
| print(" ".join(entries)) | ||
|
|
||
| def main(): | ||
| args = parse_args() | ||
| paths = get_paths(args) | ||
|
|
||
| for directory_path in paths: | ||
| list_directory( | ||
| directory_path=directory_path, | ||
| show_hidden=args.files_and_hidden_ones, | ||
| file_per_line=args.file_per_line, | ||
| ) | ||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| # Implement `wc` | ||
| # Implement `wc` in python | ||
|
|
||
| You should already be familiar with the `wc` command line tool. | ||
|
|
||
|
|
@@ -15,3 +15,20 @@ It must act the same as `wc` would, if run from the directory containing this RE | |
| Matching any additional behaviours or flags are optional stretch goals. | ||
|
|
||
| We recommend you start off supporting no flags for one file, then add support for multiple files, then add support for the flags. | ||
|
|
||
| *======Command for testing the script======== | ||
|
|
||
| * All sample files | ||
| python wc.py sample-files/* | ||
|
|
||
| * Just lines | ||
| python wc.py -l sample-files/3.txt | ||
|
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. Looks like some outputs are different? |
||
|
|
||
| * Just words | ||
| python wc.py -w sample-files/3.txt | ||
|
|
||
| * Just characters | ||
| python wc.py -c sample-files/3.txt | ||
|
|
||
| * Lines with multiple files (to see totals) | ||
| python wc.py -l sample-files/* | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| import argparse | ||
| import sys | ||
| import re | ||
|
|
||
|
|
||
| def main(): | ||
| # -------------------------------------------------------- | ||
|
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. Again, maybe try splitting into functions instead of comment blocks instead :) |
||
| # Set up argparse | ||
| # -------------------------------------------------------- | ||
| parser= argparse.ArgumentParser( | ||
| prog="wc", | ||
| description ="wc command implementation in python" | ||
| ) | ||
|
|
||
| parser.add_argument("-l", action="store_true", help ="show number of lines only") | ||
| parser.add_argument("-w", action="store_true", help="show number of words only") | ||
| parser.add_argument("-c", action="store_true", help="show number of characters only") | ||
|
|
||
| parser.add_argument("paths", nargs="*", help="file paths to process") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| # -------------------------------------------------------- | ||
| # Ensures at least one path exists | ||
| # -------------------------------------------------------- | ||
| if len(args.paths) == 0: | ||
| print("wc: no file specified", file=sys.stderr) | ||
| sys.exit(1) | ||
|
|
||
| totals= {"lines": 0, "words": 0, "chars": 0} | ||
|
|
||
| # -------------------------------------------------------- | ||
| # Loop over each file path and process it | ||
| # -------------------------------------------------------- | ||
| for file_path in args.paths: | ||
| try: | ||
| with open(file_path, "r", encoding="utf-8") as f: | ||
| content = f.read() | ||
| except OSError as err: | ||
| print(f"wc: cannot read file'{file_path}': {err}", file=sys.stderr) | ||
| continue | ||
|
|
||
| # -------------------------------------------------------- | ||
| # Count values | ||
| # -------------------------------------------------------- | ||
| line_count = len(content.split("\n")) | ||
|
|
||
| words = [w for w in re.split(r"\s+", content) if w] | ||
| word_count = len(words) | ||
|
|
||
| char_count = len(content) | ||
|
|
||
| totals["lines"] += line_count | ||
| totals["words"] += word_count | ||
| totals["chars"] +=char_count | ||
|
|
||
| # -------------------------------------------------------- | ||
| # Decide what to print based on flags | ||
| # -------------------------------------------------------- | ||
| no_flags = not args.l and not args.w and not args.c | ||
|
|
||
| if no_flags: | ||
| print(f"{line_count} {word_count} {char_count} {file_path}") | ||
| continue | ||
|
|
||
| if args.l: | ||
| print(f"{line_count} {file_path}" ) | ||
|
|
||
| if args.w: | ||
| print(f"{word_count} {file_path}") | ||
|
|
||
| if args.c: | ||
| print(f"{char_count} {file_path}") | ||
|
|
||
|
|
||
| # -------------------------------------------------------- | ||
| # Print totals if there are multiple files | ||
| # -------------------------------------------------------- | ||
| if len(args.paths) > 1: | ||
|
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. Maybe there is a way to reuse the same functions (with different args) for printing individual lines and totals |
||
| no_flags = not args.l and not args.w and not args.c | ||
|
|
||
| if no_flags: | ||
| print(f"{totals['lines']} {totals['words']} {totals['chars']} total") | ||
|
|
||
| if args.l: | ||
| print(f"{totals['lines']} total") | ||
| if args.w: | ||
| print(f"{totals['words']} total") | ||
| if args.c: | ||
| print(f"{totals['chars']} total") | ||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
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.
There is a small discrepancy in how you program handles some cases it seems: