From cdf1a3e1bfad547e390ec8cde5f09f8a9222c43f Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 15:19:05 +0000 Subject: [PATCH 01/17] update gitignore for new branch --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c3629e6..0ab4c267 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +/.venv \ No newline at end of file From df6314befc49e7bbeb7e7b858a7ed21e1bb8ad45 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 15:26:16 +0000 Subject: [PATCH 02/17] Update .gitignore to ignore node_modules and .venv folders --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0ab4c267..3cceec8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -/.venv \ No newline at end of file +/.venv +implement-cowsay/.venv/ From 29258e980fbecdeecf642f472f244a3557d68df2 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 17:51:35 +0000 Subject: [PATCH 03/17] implement basic cat --- implement-shell-tools/cat/cat.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 implement-shell-tools/cat/cat.py diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py new file mode 100644 index 00000000..9a66fedb --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,15 @@ +import sys +import glob +import argparse + +parser=argparse.ArgumentParser(prog="cat", + usage="implement a simple cat") +parser.add_argument("-n",action="store_true",help="number the output lines") +parser.add_argument("-b",action="store_true",help="number the output lines without blank ones") +parser.add_argument("path",nargs="*",help="files to read") +args=parser.parse_args() +print(args) +for per_file in args.path : + with open(per_file,"r") as f: + print(f.read()) + \ No newline at end of file From dad3daabfddc712a130fa64067705f5a1712c7d1 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 20:09:38 +0000 Subject: [PATCH 04/17] implementing flag -n --- implement-shell-tools/cat/cat.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 9a66fedb..e02171c4 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -8,8 +8,16 @@ parser.add_argument("-b",action="store_true",help="number the output lines without blank ones") parser.add_argument("path",nargs="*",help="files to read") args=parser.parse_args() -print(args) +# print(args) +line_number=1 for per_file in args.path : with open(per_file,"r") as f: - print(f.read()) + if args.n : + lines=f.readlines() + for line in lines : + print(line_number,line,end="") + line_number=line_number+1 + + + print(f.read()) \ No newline at end of file From df3aa31cc4e3dbc006b6e2bb19996dcb5537c5fc Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 20:17:46 +0000 Subject: [PATCH 05/17] implementig flag -b --- implement-shell-tools/cat/cat.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index e02171c4..dc5890cc 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -12,12 +12,14 @@ line_number=1 for per_file in args.path : with open(per_file,"r") as f: - if args.n : + if args.n or args.b : lines=f.readlines() for line in lines : - print(line_number,line,end="") - line_number=line_number+1 - - - print(f.read()) + if line=="\n" and args.b : + print(line,end="") + else : + print(line_number,line,end="") + line_number=line_number+1 + else : + print(f.read()) \ No newline at end of file From fc93e9280c62d11d3f6036864b911ba633548ade Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 20:21:28 +0000 Subject: [PATCH 06/17] fixing a bug --- implement-shell-tools/cat/cat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index dc5890cc..d2f32bdb 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -21,5 +21,5 @@ print(line_number,line,end="") line_number=line_number+1 else : - print(f.read()) + print(f.read(),end="") \ No newline at end of file From 3d571eb616e6e979c84f0b1ee2b2b6d047aae43f Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 21:03:03 +0000 Subject: [PATCH 07/17] implementing ls -1 --- implement-shell-tools/ls/ls.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 implement-shell-tools/ls/ls.py diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py new file mode 100644 index 00000000..bf8a7a11 --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,18 @@ +import os +import argparse + +parser=argparse.ArgumentParser(prog="cat",usage="implement a simple ls python") +parser.add_argument("-1",dest="one",action="store_true") +parser.add_argument("-a",action="store_true") +parser.add_argument("path",nargs="*",help="path to list files") +args=parser.parse_args() + +paths=args.path +if len(paths)==0 : paths=["."] + +for path in paths : + files_list=os.listdir(path) + files_list.sort(key=str.lower) +if args.one : + for item in files_list : + print(item) \ No newline at end of file From 1766ec3c17f63ff4ffbda8ac25d5f22879a0eaa4 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 21:14:56 +0000 Subject: [PATCH 08/17] implementing ls -a --- implement-shell-tools/ls/ls.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index bf8a7a11..a504cf9e 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -13,6 +13,9 @@ for path in paths : files_list=os.listdir(path) files_list.sort(key=str.lower) -if args.one : - for item in files_list : - print(item) \ No newline at end of file +for item in files_list : + if args.one and args.a : + print(item) + elif args.one : + if not item.startswith(".") : + print(item) From b9dc023e8e909d65fc999dcdeb3bd4c5ca905e4a Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Wed, 26 Nov 2025 21:25:25 +0000 Subject: [PATCH 09/17] removing non usable imports from cat implementation --- implement-shell-tools/cat/cat.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index d2f32bdb..99c42b4a 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -1,5 +1,3 @@ -import sys -import glob import argparse parser=argparse.ArgumentParser(prog="cat", From a35d9757243f3d1e073d82421608cae84795c9e4 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Thu, 27 Nov 2025 20:19:09 +0000 Subject: [PATCH 10/17] implement basic wc --- implement-shell-tools/wc/wc.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 implement-shell-tools/wc/wc.py diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py new file mode 100644 index 00000000..07e303eb --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,12 @@ +import argparse + +parser=argparse.ArgumentParser(prog="wc",usage="implement a simple wc in python") +parser.add_argument("path",nargs="+") +args=parser.parse_args() + +print(args.path) +paths=args.path +for path in paths : + with open(path,"r") as f : + lines=f.readlines() + print(len(lines) , path) \ No newline at end of file From cb495884f310e336a9275a3e51d399d7932a2abd Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Thu, 27 Nov 2025 21:06:02 +0000 Subject: [PATCH 11/17] improving basic wc --- implement-shell-tools/wc/wc.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 07e303eb..e6d0aaf2 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -1,12 +1,28 @@ import argparse +import os parser=argparse.ArgumentParser(prog="wc",usage="implement a simple wc in python") parser.add_argument("path",nargs="+") args=parser.parse_args() -print(args.path) +# print(args.path) paths=args.path -for path in paths : - with open(path,"r") as f : +words_count=0 +total_lines=0 +total_words=0 +total_bytes=0 + +for file in paths : + with open(file,"r") as f : + bytes_count=os.path.getsize(file) lines=f.readlines() - print(len(lines) , path) \ No newline at end of file + lines_count=len(lines) + for line in lines : + words_count+=len(line.split()) + total_lines +=lines_count + total_bytes += bytes_count + total_words +=words_count + print(lines_count ,words_count , bytes_count, file) + words_count=0 + +print(total_lines,total_words,total_bytes,"total") \ No newline at end of file From b41d36a73f7d3b38afb8f7c00ce7013e01aefee4 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Thu, 27 Nov 2025 21:12:11 +0000 Subject: [PATCH 12/17] formati printing --- implement-shell-tools/wc/wc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index e6d0aaf2..c71bc772 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -22,7 +22,7 @@ total_lines +=lines_count total_bytes += bytes_count total_words +=words_count - print(lines_count ,words_count , bytes_count, file) + print(f"{lines_count:<5}{words_count:<5}{bytes_count:<5}{file:<20}") words_count=0 -print(total_lines,total_words,total_bytes,"total") \ No newline at end of file +print(f"{total_lines:<5}{total_words:<5}{total_bytes:<5}total") \ No newline at end of file From 9b645e672a6961e7763a2883cd1b62e10dfb4e80 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Thu, 27 Nov 2025 21:40:19 +0000 Subject: [PATCH 13/17] implementing flags --- implement-shell-tools/wc/wc.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index c71bc772..29cd4534 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -2,10 +2,13 @@ import os parser=argparse.ArgumentParser(prog="wc",usage="implement a simple wc in python") +parser.add_argument("-l",action="store_true",help="count of lines") +parser.add_argument("-w",action="store_true",help="count of words") +parser.add_argument("-c",action="store_true",help="count of bytes") parser.add_argument("path",nargs="+") args=parser.parse_args() -# print(args.path) +print(args) paths=args.path words_count=0 total_lines=0 @@ -21,8 +24,15 @@ words_count+=len(line.split()) total_lines +=lines_count total_bytes += bytes_count - total_words +=words_count - print(f"{lines_count:<5}{words_count:<5}{bytes_count:<5}{file:<20}") + total_words +=words_count + if not (args.l or args.w or args.c): + args.l = True + args.w = True + args.c = True + print((f"{lines_count:<5}" if args.l else "")+ + (f"{words_count:<5}" if args.w else "")+ + (f"{bytes_count:<5}" if args.c else "")+ + f"{file:<20}") words_count=0 print(f"{total_lines:<5}{total_words:<5}{total_bytes:<5}total") \ No newline at end of file From 516af11763f8e761e914650097e8b330dbaf5686 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Thu, 27 Nov 2025 21:47:40 +0000 Subject: [PATCH 14/17] fixing bug and improving code --- implement-shell-tools/wc/wc.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 29cd4534..db1ad103 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -8,7 +8,7 @@ parser.add_argument("path",nargs="+") args=parser.parse_args() -print(args) + paths=args.path words_count=0 total_lines=0 @@ -34,5 +34,9 @@ (f"{bytes_count:<5}" if args.c else "")+ f"{file:<20}") words_count=0 - -print(f"{total_lines:<5}{total_words:<5}{total_bytes:<5}total") \ No newline at end of file + +if len(paths)>1 : + print((f"{total_lines:<5}" if args.l else "")+ + (f"{total_words:<5}" if args.w else "")+ + (f"{total_bytes:<5}" if args.c else "")+ + "total") \ No newline at end of file From 4ebe46117503c70b5e6f1600f48f08e4502d70e2 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Fri, 23 Jan 2026 17:47:33 +0000 Subject: [PATCH 15/17] Refactored argparse setup for better readability and clearer help messages --- implement-shell-tools/cat/cat.py | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index 99c42b4a..019c5d81 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -1,11 +1,32 @@ import argparse -parser=argparse.ArgumentParser(prog="cat", - usage="implement a simple cat") -parser.add_argument("-n",action="store_true",help="number the output lines") -parser.add_argument("-b",action="store_true",help="number the output lines without blank ones") -parser.add_argument("path",nargs="*",help="files to read") -args=parser.parse_args() +parser = argparse.ArgumentParser( + prog="cat", + usage="implement a simple cat" +) + +# Flag to number all lines +parser.add_argument( + "-n", + action="store_true", + help="Number all output lines" +) + +# Flag to number only non-blank lines +parser.add_argument( + "-b", + action="store_true", + help="Number non-blank output lines" +) + +# Positional argument for files to read +parser.add_argument( + "path", + nargs="*", + help="Files to read" +) + +args = parser.parse_args() # print(args) line_number=1 for per_file in args.path : From 152590c13e6e16ede482434a996874372adf3440 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Fri, 23 Jan 2026 18:56:04 +0000 Subject: [PATCH 16/17] Fix -a output order to match ls: non-hidden files first, hidden files last, with '.' and '..' at the top --- implement-shell-tools/ls/ls.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index a504cf9e..b380cd6b 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -13,6 +13,21 @@ for path in paths : files_list=os.listdir(path) files_list.sort(key=str.lower) + + # Divide into hidden and non-hidden + non_hidden = [f for f in files_list if not f.startswith(".")] + hidden = [f for f in files_list if f.startswith(".")] + + # Sort each list + non_hidden.sort(key=str.lower) + hidden.sort(key=str.lower) + + # Add '.' and '..' at the start if -a + if args.a: + files_list = ['.', '..'] + non_hidden + hidden + else: + files_list = non_hidden + for item in files_list : if args.one and args.a : print(item) From be7004743106caa28b13d8cf77e0ee6528a7bb28 Mon Sep 17 00:00:00 2001 From: sheida-shab Date: Fri, 23 Jan 2026 19:19:34 +0000 Subject: [PATCH 17/17] Remove duplicate wc print code for readability --- implement-shell-tools/wc/wc.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index db1ad103..1fd7e660 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -1,6 +1,8 @@ import argparse import os + +# Set up argument parser for wc command parser=argparse.ArgumentParser(prog="wc",usage="implement a simple wc in python") parser.add_argument("-l",action="store_true",help="count of lines") parser.add_argument("-w",action="store_true",help="count of words") @@ -15,28 +17,42 @@ total_words=0 total_bytes=0 +# Function to print counts for a file or total +def print_wc(lines, words, bytes_, name): + # Print selected counts in formatted columns + print( + (f"{lines:<5}" if args.l else "") + + (f"{words:<5}" if args.w else "") + + (f"{bytes_:<5}" if args.c else "") + + f"{name:<20}" + ) + +# Loop through all files for file in paths : with open(file,"r") as f : + # Get file size in bytes bytes_count=os.path.getsize(file) + # Read all lines lines=f.readlines() lines_count=len(lines) for line in lines : + # Count words in file words_count+=len(line.split()) + + # Update totals total_lines +=lines_count total_bytes += bytes_count total_words +=words_count + + # If no flags provided, default to showing all counts if not (args.l or args.w or args.c): args.l = True args.w = True args.c = True - print((f"{lines_count:<5}" if args.l else "")+ - (f"{words_count:<5}" if args.w else "")+ - (f"{bytes_count:<5}" if args.c else "")+ - f"{file:<20}") - words_count=0 + # Print counts for this file + print_wc(lines_count, words_count, bytes_count, file) +# If multiple files, print totals at the end if len(paths)>1 : - print((f"{total_lines:<5}" if args.l else "")+ - (f"{total_words:<5}" if args.w else "")+ - (f"{total_bytes:<5}" if args.c else "")+ - "total") \ No newline at end of file + print_wc(total_lines, total_words, total_bytes, "total") +