Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions implement-shell-tools/cat/cat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import argparse
import os

parser = argparse.ArgumentParser(
prog="cat",
description="Concatenate and print files",
)

parser.add_argument(
"-n", action="store_true", help="Number the output lines, starting at 1"
)
parser.add_argument(
"-b", action="store_true", help="Number the non-blank output lines, starting at 1"
)
parser.add_argument("path", nargs="+", help="The path to search")

args = parser.parse_args()
for path in args.path:
if os.path.isfile(path):
with open(path) as file:
lines = file.readlines()
line_num = 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I pass in multiple files the numbering still isn't quite working right here. Think about when you might want to use cat with multiple files, and why you might number the lines. How should the application behave in those cases?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I’m not sure what part isn’t working. When I run the cat command in the console with the -n flag and multiple files, I get this output:

cyf@cyfs-MacBook-Pro cat % cat -n sample-files/*.txt
     1  Once upon a time...
     1  There was a house made of gingerbread.
     1  It looked delicious.
     2  I was tempted to take a bite of it.
     3  But this seemed like a bad idea...
     4
     5  There's more to come, though...

When I run the same with my command, I get the same result:

cyf@cyfs-MacBook-Pro cat % python3 cat.py -n  sample-files/*.txt
     1  Once upon a time...
     1  There was a house made of gingerbread.
     1  It looked delicious.
     2  I was tempted to take a bite of it.
     3  But this seemed like a bad idea...
     4  
     5  There's more to come, though...

for line in lines:
lin = line.rstrip("\n")
if args.b:
if lin == "":
print()
else:
print(str(line_num).rjust(6), lin)
line_num += 1
elif args.n:
print(str(line_num).rjust(6), "", lin)
line_num += 1

else:
print(lin)
else:
print(f"cat: {path}: Is a directory")
41 changes: 41 additions & 0 deletions implement-shell-tools/ls/ls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os
import argparse

parser = argparse.ArgumentParser(
prog="ls",
description="list directory contents",
)

parser.add_argument("-1",dest="one",action='store_true', help="list one file per line")
parser.add_argument("-a", action='store_true', help="Used to list all files, including hidden files, in the current directory")
parser.add_argument("path", nargs="?", default=".", help="The path to search")

args = parser.parse_args()

def arguments_proceeding(files):
data_to_proceed = files

if args.a:
data_to_proceed = [f for f in files]
data_to_proceed.sort()
data_to_proceed.insert(0, "..")
data_to_proceed.insert(0, ".")
else:
data_to_proceed = [f for f in files if not f.startswith('.')]
data_to_proceed.sort(key=str.lower)
if args.one:
output = [f for f in data_to_proceed]
for f in output:
print(f)
else:
print(" ".join(data_to_proceed))


def path_proceeding(path_argument):
if os.path.isfile(path_argument):
print(path_argument)
elif os.path.isdir(path_argument):
files = os.listdir(path_argument)
arguments_proceeding(files)

path_proceeding(args.path)
75 changes: 75 additions & 0 deletions implement-shell-tools/wc/wc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import os
import argparse

parser = argparse.ArgumentParser(
prog="wc",
description="Counts words in a file that contain a particular character",
)

parser.add_argument(
"-l",
action="store_true",
help="The number of lines in each input file is written to the standard output.",
)
parser.add_argument(
"-w",
action="store_true",
help="The number of words in each input file is written to the standard output.",
)
parser.add_argument(
"-c",
action="store_true",
help="The number of bytes in each input file is written to the standard output.",
)
parser.add_argument("path", nargs="+", help="The path to search")

args = parser.parse_args()

if not args.w and not args.c and not args.l:
args.w = args.c = args.l = True
per_file_totals = []
output = []
column_widths = []
for path in args.path:
output_for_one_file = []
if args.l or args.w:
with open(path) as file:
lines = file.readlines()
# lines count
if args.l:
num_lines = len(lines)
output_for_one_file.append(num_lines)
# word count
if args.w:
word_count = 0
for line in lines:
lin = line.rstrip()
wds = lin.split()
word_count += len(wds)

output_for_one_file.append(word_count)

if args.c:
file_size = os.path.getsize(path)
output_for_one_file.append(file_size)

if len(args.path) > 1:
per_file_totals.append(output_for_one_file.copy())
output_for_one_file.append(path)
output.append(output_for_one_file)
if len(args.path) > 1:
total_results = [sum(i) for i in zip(*per_file_totals)]
total_results.append("total")
output.append(total_results)

num_cols = len(total_results) - 1
column_widths = [len(str(total_results[i])) for i in range(num_cols)]
elif len(args.path) == 1:
num_cols = len(output[0]) - 1
column_widths = [len(str([output[0][i]])) for i in range(num_cols)]
for row in output:
line_parts = []
for i in range(num_cols):
# Right-align with 1 space padding (like wc)
line_parts.append(str(row[i]).rjust(column_widths[i] + 6))
print("".join(line_parts), row[-1])