From e0b7ca4fca2f5ac54aaf6e8ca5628a47f363963d Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Mon, 6 Apr 2026 19:43:56 +0100 Subject: [PATCH 1/7] feat:implement cat CLI tool --- implement-shell-tools/cat/cat.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 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 000000000..db1ed787d --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,32 @@ +import argparse + +parser = argparse.ArgumentParser( + prog="cat", + description="implement cat", +) + +parser.add_argument("paths",nargs="+",help="The file to process") +parser.add_argument("-n",action="store_true",help= "Number all lines") +parser.add_argument("-b",action="store_true",help="Number non-empty lines only") + +args =parser.parse_args(); +counter =1 + +for path in args.paths: + with open(path,"r") as f: + for line in f: + if(args.n): + print(f"\t{counter} {line}",end="") + counter+=1 + elif(args.b): + if(line.strip()!=""): + print(f"\t{counter} {line}",end="") + counter+=1 + else: + print(f"\t {line}",end="") + else: + print(f" {line}",end="") + + + + \ No newline at end of file From 6b4fda4ed0fdf989168d5f4f7a8d8d81f2313fba Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Mon, 6 Apr 2026 22:45:03 +0100 Subject: [PATCH 2/7] reformatted --- implement-shell-tools/cat/cat.py | 38 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/implement-shell-tools/cat/cat.py b/implement-shell-tools/cat/cat.py index db1ed787d..1384fcfed 100644 --- a/implement-shell-tools/cat/cat.py +++ b/implement-shell-tools/cat/cat.py @@ -5,28 +5,24 @@ description="implement cat", ) -parser.add_argument("paths",nargs="+",help="The file to process") -parser.add_argument("-n",action="store_true",help= "Number all lines") -parser.add_argument("-b",action="store_true",help="Number non-empty lines only") +parser.add_argument("paths", nargs="+", help="The file to process") +parser.add_argument("-n", action="store_true", help="Number all lines") +parser.add_argument("-b", action="store_true", help="Number non-empty lines only") -args =parser.parse_args(); -counter =1 +args = parser.parse_args() +counter = 1 for path in args.paths: - with open(path,"r") as f: - for line in f: - if(args.n): - print(f"\t{counter} {line}",end="") - counter+=1 - elif(args.b): - if(line.strip()!=""): - print(f"\t{counter} {line}",end="") - counter+=1 + with open(path, "r") as f: + for line in f: + if args.n: + print(f"\t{counter} {line}", end="") + counter += 1 + elif args.b: + if line.strip() != "": + print(f"\t{counter} {line}", end="") + counter += 1 + else: + print(f"\t {line}", end="") else: - print(f"\t {line}",end="") - else: - print(f" {line}",end="") - - - - \ No newline at end of file + print(f" {line}", end="") \ No newline at end of file From a0c5a81a8734942f528c3c40eb62ac49161c8276 Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Mon, 6 Apr 2026 23:29:23 +0100 Subject: [PATCH 3/7] implement wc for one file with flags --- implement-shell-tools/wc/wc.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 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 000000000..4ac22c1f7 --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,30 @@ +import argparse + +parser = argparse.ArgumentParser( + prog="wc", + description="wc implementation", +) + +parser.add_argument("path", help="The file to process") +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 characters") + + +args =parser.parse_args() +with open(args.path,"r") as f: + content = f.read() + +line_counter = len(content.split("\n"))-1 +words_counter = len(content.split()) +characters_counter = len(content) +if(not args.l and not args.w and not args.c): + print(f"{line_counter} {words_counter} {characters_counter} {args.path}") + +else: + results = [] + if(args.l):results.append(line_counter) + if(args.w):results.append(words_counter) + if(args.c):results.append(characters_counter) + results=" ".join(map(str,results)) + print(results,args.path) From 57914a3351c7ba5973b14b8b39ee249bc0fff7a9 Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Mon, 6 Apr 2026 23:35:14 +0100 Subject: [PATCH 4/7] add multiple files without totatl --- implement-shell-tools/wc/wc.py | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 4ac22c1f7..6a6f00f9f 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -5,26 +5,30 @@ description="wc implementation", ) -parser.add_argument("path", help="The file to process") +parser.add_argument("paths", nargs="+", help="The file to process") 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 characters") +args = parser.parse_args() +for path in args.paths: -args =parser.parse_args() -with open(args.path,"r") as f: - content = f.read() + with open(path, "r") as f: + content = f.read() -line_counter = len(content.split("\n"))-1 -words_counter = len(content.split()) -characters_counter = len(content) -if(not args.l and not args.w and not args.c): - print(f"{line_counter} {words_counter} {characters_counter} {args.path}") + line_counter = len(content.split("\n")) - 1 + words_counter = len(content.split()) + characters_counter = len(content) + if not args.l and not args.w and not args.c: + print(f"{line_counter} {words_counter} {characters_counter} {args.path}") -else: - results = [] - if(args.l):results.append(line_counter) - if(args.w):results.append(words_counter) - if(args.c):results.append(characters_counter) - results=" ".join(map(str,results)) - print(results,args.path) + else: + results = [] + if args.l: + results.append(line_counter) + if args.w: + results.append(words_counter) + if args.c: + results.append(characters_counter) + results = " ".join(map(str, results)) + print(results, path) From 8d8af3bf6554b3d247dcb47310af9098e5339e5f Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Tue, 7 Apr 2026 11:51:50 +0100 Subject: [PATCH 5/7] implement wc CLI tool done --- implement-shell-tools/wc/wc.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/wc/wc.py b/implement-shell-tools/wc/wc.py index 6a6f00f9f..44e350558 100644 --- a/implement-shell-tools/wc/wc.py +++ b/implement-shell-tools/wc/wc.py @@ -11,6 +11,11 @@ parser.add_argument("-c", action="store_true", help="count characters") args = parser.parse_args() +total = { + "lines_counter": 0, + "words_counter": 0, + "characters_counter": 0, +} for path in args.paths: with open(path, "r") as f: @@ -20,15 +25,38 @@ words_counter = len(content.split()) characters_counter = len(content) if not args.l and not args.w and not args.c: - print(f"{line_counter} {words_counter} {characters_counter} {args.path}") - + print(f"{line_counter} {words_counter} {characters_counter} {path}") + total["lines_counter"] += line_counter + total["words_counter"] += words_counter + total["characters_counter"] += characters_counter else: results = [] if args.l: results.append(line_counter) + total["lines_counter"] += line_counter if args.w: results.append(words_counter) + total["words_counter"] += words_counter if args.c: results.append(characters_counter) + total["characters_counter"] += characters_counter results = " ".join(map(str, results)) print(results, path) + +if len(args.paths) > 1: + if not args.l and not args.w and not args.c: + print( + f"{total['lines_counter']} {total['words_counter']} {total['characters_counter']} total" + ) + + else: + total_with_flags = [] + + if args.l: + total_with_flags.append(total["lines_counter"]) + if args.w: + total_with_flags.append(total["words_counter"]) + if args.c: + total_with_flags.append(total["characters_counter"]) + print(" ".join(map(str, total_with_flags))," total") + From e0be462463a577031ea12cd5908151c660998f6d Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Tue, 7 Apr 2026 15:00:26 +0100 Subject: [PATCH 6/7] feat: implement ls CLI tool --- implement-shell-tools/ls/ls.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 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 000000000..2a73f2897 --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,34 @@ +import argparse +from pathlib import Path + +parser = argparse.ArgumentParser( + prog="wc", + description="wc implementation", +) + +parser.add_argument("path", nargs="?", help="The file to process", default=".") +parser.add_argument("-1", "--one_per_line",action="store_true", help="one file per line") +parser.add_argument("-a", action="store_true", help="Show hidden files") + + +args = parser.parse_args() + +path = Path(args.path) # path is an object represent a location on disk + +# else: +# for item in path.iterdir(): # iterdir is a method reads directory contents +# if args.a: +# print(item.name) +# else: +# if not item.name.startswith("."): +# print(item.name) # each item is a Path object +items =[] +for item in sorted(path.iterdir()): + if args.a or not item.name.startswith("."): + items.append(item.name) + +if(args.one_per_line): + for name in items: + print(name) +else: + print(" ".join(items)) \ No newline at end of file From 3a816e4d9e8805729ca46a41d1b13f26745d3f91 Mon Sep 17 00:00:00 2001 From: Ahmad Hmedan Date: Tue, 7 Apr 2026 15:01:28 +0100 Subject: [PATCH 7/7] clean the code --- implement-shell-tools/ls/ls.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/implement-shell-tools/ls/ls.py b/implement-shell-tools/ls/ls.py index 2a73f2897..dba80180e 100644 --- a/implement-shell-tools/ls/ls.py +++ b/implement-shell-tools/ls/ls.py @@ -7,28 +7,23 @@ ) parser.add_argument("path", nargs="?", help="The file to process", default=".") -parser.add_argument("-1", "--one_per_line",action="store_true", help="one file per line") +parser.add_argument( + "-1", "--one_per_line", action="store_true", help="one file per line" +) parser.add_argument("-a", action="store_true", help="Show hidden files") args = parser.parse_args() -path = Path(args.path) # path is an object represent a location on disk - -# else: -# for item in path.iterdir(): # iterdir is a method reads directory contents -# if args.a: -# print(item.name) -# else: -# if not item.name.startswith("."): -# print(item.name) # each item is a Path object -items =[] +path = Path(args.path) + +items = [] for item in sorted(path.iterdir()): if args.a or not item.name.startswith("."): items.append(item.name) -if(args.one_per_line): +if args.one_per_line: for name in items: print(name) else: - print(" ".join(items)) \ No newline at end of file + print(" ".join(items))