diff --git a/implement-shell-tools/cat/my_cat.py b/implement-shell-tools/cat/my_cat.py new file mode 100644 index 00000000..fb3b4e11 --- /dev/null +++ b/implement-shell-tools/cat/my_cat.py @@ -0,0 +1,37 @@ +import argparse + +parser = argparse.ArgumentParser( + prog="cat", + description="Read, display, and concatenate text files.", +) + +parser.add_argument("-n", "--number", action="store_true", help="Number all output lines.") +parser.add_argument("-b", "--number-nonblank", action="store_true", help="Number non-blank output lines.") +parser.add_argument("paths", nargs="+", help="The file(s) to read.") + +args = parser.parse_args() + +for path in args.paths: + try: + with open(path, mode='r', encoding='utf-8') as f: + lines = f.readlines() + except Exception as err: + print(f"Error reading file '{path}': {err}") + continue + + line_num = 1 + + for line in lines: + should_number = False + if args.number_nonblank and line.strip(): + should_number = True + elif args.number and not args.number_nonblank: + should_number = True + + if should_number: + print(f"{line_num:6}\t{line}", end="") + line_num += 1 + else: + print(line, end="") + + \ No newline at end of file diff --git a/implement-shell-tools/ls/my_ls.py b/implement-shell-tools/ls/my_ls.py new file mode 100644 index 00000000..ecb13c65 --- /dev/null +++ b/implement-shell-tools/ls/my_ls.py @@ -0,0 +1,31 @@ +import os +import argparse + +parser = argparse.ArgumentParser( + prog="ls", + description="List directory contents." +) + +parser.add_argument("-1", "--one-per-line", action="store_true", help="List one file per line") +parser.add_argument("-a", "--all", action="store_true", help="Include hidden files (those starting with .)") +parser.add_argument("paths", nargs="*", default=["."], help="Directory path(s) to list") + +args = parser.parse_args() + +for path in args.paths: + try: + entries = os.listdir(path) + except Exception as e: + print(f"ls: cannot access '{path}': {e}") + continue + + if not args.all: + entries = [entry for entry in entries if not entry.startswith(".")] + + entries.sort() + + if args.one_per_line: + for entry in entries: + print(entry) + else: + print(" ".join(entries)) diff --git a/implement-shell-tools/wc/my_wc.py b/implement-shell-tools/wc/my_wc.py new file mode 100644 index 00000000..6d12f082 --- /dev/null +++ b/implement-shell-tools/wc/my_wc.py @@ -0,0 +1,52 @@ +import argparse + +parser = argparse.ArgumentParser( + prog="wc", + description="Counts lines, words, and bytes in text files." +) + +parser.add_argument("-l", "--lines", action="store_true", help="Print the line counts") +parser.add_argument("-w", "--words", action="store_true", help="Print the word counts") +parser.add_argument("-c", "--bytes", action="store_true", help="Print the byte counts") +parser.add_argument("paths", nargs="+", help="One or more files to process") + +args = parser.parse_args() + +if not (args.lines or args.words or args.bytes): + args.lines = args.words = args.bytes = True + +total_lines = total_words = total_bytes = 0 + +for path in args.paths: + try: + with open(path, "rb") as file: + content = file.read() + except Exception as e: + print(f"wc: {path}: {e}") + continue + + lines = content.count(b'\n') + words = len(content.decode('utf-8', errors='ignore').split()) + byte_count = len(content) + + if args.lines: + print(f"{lines:>8}", end=" ") + if args.words: + print(f"{words:>8}", end=" ") + if args.bytes: + print(f"{byte_count:>8}", end=" ") + + print(f"{path}") + + total_lines += lines + total_words += words + total_bytes += byte_count + +if len(args.paths) > 1: + if args.lines: + print(f"{total_lines:>8}", end=" ") + if args.words: + print(f"{total_words:>8}", end=" ") + if args.bytes: + print(f"{total_bytes:>8}", end=" ") + print("total") diff --git a/individual-shell-tools/ls/script-01.sh b/individual-shell-tools/ls/script-01.sh deleted file mode 100755 index 241b62f5..00000000 --- a/individual-shell-tools/ls/script-01.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -# Do not change this part of the script - only change after the TODO comment. - -script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" -if [[ "${script_dir}" != "$(pwd)" ]]; then - echo >&2 "ERROR: You haven't cd'd into the correct directory." - echo >&2 "For each exercise, you should cd to the directory containing the script before running it." - exit 1 -fi - -# TODO: Write a command to list the files and folders in this directory. -# The output should be a list of names including child-directory, script-01.sh, script-02.sh, and more. diff --git a/individual-shell-tools/ls/script-02.sh b/individual-shell-tools/ls/script-02.sh deleted file mode 100755 index d0a5a10f..00000000 --- a/individual-shell-tools/ls/script-02.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -# TODO: Write a command which lists all of the files in the directory named child-directory. -# The output should be a list of names: helper-1.txt, helper-2.txt, helper-3.txt.