diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py new file mode 100644 index 00000000..2485cd7e --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,60 @@ +import argparse +import sys + +def main(): + parser = argparse.ArgumentParser( + prog="display-content-of-a-file", + description="cat is used to display the content of a file or print the content of a file." + ) + parser.add_argument('-n', action='store_true', help='number output lines') + parser.add_argument('-b', action='store_true', help='number non-empty output lines') + parser.add_argument('paths', nargs='+', help="The file path(s) to process") + + options = parser.parse_args() + + combined_data = "" + for path in options.paths: + try: + with open(path, 'r', encoding='utf-8') as f: + combined_data += f.read() + "\n" + except Exception as e: + print(f"Error reading {path}: {e}", file=sys.stderr) + sys.exit(1) + + # If user used -b + if options.b: + line_num = 1 + numbered_lines = [] + for line in combined_data.split('\n'): + if line.strip() == '': + numbered_lines.append(line) # Keep empty lines unnumbered + else: + numbered_lines.append(f"{line_num:6} {line}") + line_num += 1 + sys.stdout.write('\n'.join(numbered_lines) + '\n') + + # If user used -n + elif options.n: + numbered_lines = [ + f"{i+1:6} {line}" + for i, line in enumerate(combined_data.split('\n')) + ] + sys.stdout.write('\n'.join(numbered_lines) + '\n') + + # If user didn't use -n or -b + else: + sys.stdout.write(combined_data) + +if __name__ == "__main__": + main() + + + + + + + + + + +#python3 cat.py -b sample-files/* \ No newline at end of file diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py new file mode 100644 index 00000000..ea16010a --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,37 @@ +import argparse #for parsing command-line arguments and options +import os #to interact with the os for listing files and handling paths +import sys #Allows interaction with the Py runtime env like reading/writing output,exiting. + + +def list_directory(directory, show_all, one_per_line): + try: + files = os.listdir(directory) + except Exception as e: + print(f"ls: cannot access '{directory}': {e}", file=sys.stderr) + return 1 + + if not show_all: + files = [f for f in files if not f.startswith('.')] + files.sort() + + if one_per_line: + for file in files: + print(file) + else: + print(' '.join(files)) + + return 0 + +def main(): + parser = argparse.ArgumentParser(description="A simplified ls implementation.") + parser.add_argument('-1', dest='one_per_line', action='store_true', help='list one file per line') + parser.add_argument('-a', action='store_true', help='include hidden files') + parser.add_argument('directory', nargs='?', default='.', help='directory to list (default: current directory)') + + args = parser.parse_args() + + exit_code = list_directory(args.directory, args.a, args.one_per_line) + sys.exit(exit_code) + +if __name__ == "__main__": + main() diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py new file mode 100644 index 00000000..26165b0d --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,49 @@ +import argparse +import sys +import os + +def format_output(lines, words, bytes_, label, options): + output = "" + if not (options.l or options.w or options.c): + output += f"{lines:8}{words:8}{bytes_:8}" + else: + if options.l: + output += f"{lines:8}" + if options.w: + output += f"{words:8}" + if options.c: + output += f"{bytes_:8}" + return f"{output} {label}" + +def main(): + parser = argparse.ArgumentParser(description="Count lines, words, and bytes in files (like wc)") + parser.add_argument("-l", action="store_true", help="count lines") + parser.add_argument("-w", action="store_true", help="count words") + parser.add_argument("-c", action="store_true", help="count bytes") + parser.add_argument("files", nargs="+", help="files to read") + options = parser.parse_args() + + total_lines = total_words = total_bytes = 0 + + for file_path in options.files: + try: + with open(file_path, "r", encoding="utf-8") as f: + data = f.read() + + lines = data.count("\n") + words = len(data.split()) + bytes_ = len(data.encode("utf-8")) + + total_lines += lines + total_words += words + total_bytes += bytes_ + + print(format_output(lines, words, bytes_, os.path.basename(file_path), options)) + except Exception as e: + print(f"Error reading {file_path}: {e}", file=sys.stderr) + + if len(options.files) > 1: + print(format_output(total_lines, total_words, total_bytes, "total", options)) + +if __name__ == "__main__": + main()