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
3 changes: 3 additions & 0 deletions implement-shell-tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.venv/
__pycache__/
*.pyc
41 changes: 41 additions & 0 deletions implement-shell-tools/cat/sample-files/mycat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
import sys
import os

def print_file(filename, number_all=False, number_nonempty=False):
try:
with open(filename, 'r') as f:
lines = f.readlines()
except FileNotFoundError:
print(f"cat: {filename}: No such file")
return

counter = 1
for line in lines:
line = line.rstrip('\n')
if number_all:
print(f"{counter:6} {line}")
counter += 1
elif number_nonempty:
if line.strip():
print(f"{counter:6} {line}")
counter += 1
else:
print(line)
else:
print(line)

def main():
import argparse

parser = argparse.ArgumentParser(description="A Python implementation of cat")
parser.add_argument('files', nargs='+', help="Files to print")
parser.add_argument('-n', '--number-all', action='store_true', help="Number all lines")
parser.add_argument('-b', '--number-nonempty', action='store_true', help="Number non-empty lines")
args = parser.parse_args()

for file in args.files:
print_file(file, number_all=args.number_all, number_nonempty=args.number_nonempty)

if __name__ == "__main__":
main()
40 changes: 40 additions & 0 deletions implement-shell-tools/ls/sample-files/myls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
import argparse
import os

def list_directory(dir_path, show_all):
if not os.path.exists(dir_path):
print(f"ls: cannot access '{dir_path}': No such file or directory")
return

if os.path.isfile(dir_path):
print(dir_path)
return

try:
entries = os.listdir(dir_path)
except PermissionError:
print(f"ls: cannot access '{dir_path}': Permission denied")
return

if not show_all:
entries = [e for e in entries if not e.startswith(".")]
else:
entries = [".", ".."] + entries

entries.sort()
for e in entries:
print(e)

def main():
parser = argparse.ArgumentParser(description="Custom implementation of ls")
parser.add_argument("-1", action="store_true", help="list one file per line (default)")
parser.add_argument("-a", "--all", action="store_true", help="include hidden files")
parser.add_argument("dir", nargs="?", default=".", help="directory to list")

args = parser.parse_args()

list_directory(args.dir, args.all)

if __name__ == "__main__":
main()
79 changes: 79 additions & 0 deletions implement-shell-tools/wc/sample-files/mywc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
import argparse
import glob
import os

def count_lines(text):
if not text:
return 0
lines = text.splitlines()
return len(lines)

def count_words(text):
return len([w for w in text.split() if w])

def count_chars(text):
return len(text.encode('utf-8'))

def wc_file(filename, options):
try:
with open(filename, "r", encoding="utf-8") as f:
text = f.read()
except FileNotFoundError:
print(f"wc: {filename}: No such file")
return None

lines = count_lines(text)
words = count_words(text)
chars = count_chars(text)

padding = 7
if options.lines and not options.words and not options.chars:
output = f"{lines} {filename}"
elif options.words and not options.lines and not options.chars:
output = f"{words} {filename}"
elif options.chars and not options.lines and not options.words:
output = f"{chars} {filename}"
else:
output = f"{str(lines).rjust(padding)} {str(words).rjust(padding)} {str(chars).rjust(padding)} {filename}"

print(output)
return {"lines": lines, "words": words, "chars": chars}

def main():
parser = argparse.ArgumentParser(description="Custom implementation of wc")
parser.add_argument("-l", "--lines", action="store_true", help="count lines")
parser.add_argument("-w", "--words", action="store_true", help="count words")
parser.add_argument("-c", "--chars", action="store_true", help="count characters")
parser.add_argument("files", nargs="+", help="files or wildcard patterns")
args = parser.parse_args()

all_files = []
for pattern in args.files:
expanded = glob.glob(pattern)
if not expanded:
print(f"wc: {pattern}: No such file or directory")
all_files.extend(expanded)

total_lines = total_words = total_chars = 0

for file in all_files:
result = wc_file(file, args)
if result:
total_lines += result["lines"]
total_words += result["words"]
total_chars += result["chars"]

padding = 7
if len(all_files) > 1:
if args.lines and not args.words and not args.chars:
print(f"{total_lines} total")
elif args.words and not args.lines and not args.chars:
print(f"{total_words} total")
elif args.chars and not args.lines and not args.words:
print(f"{total_chars} total")
else:
print(f"{str(total_lines).rjust(padding)} {str(total_words).rjust(padding)} {str(total_chars).rjust(padding)} total")

if __name__ == "__main__":
main()