From a209f58a9b9f29da7455af99cd4072724229b651 Mon Sep 17 00:00:00 2001 From: TarasMykytiuk Date: Thu, 23 Apr 2026 01:39:29 +0300 Subject: [PATCH 1/3] cat.py command --- implement-shell-tools/cat/cat.py | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 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..6368e4b49 --- /dev/null +++ b/implement-shell-tools/cat/cat.py @@ -0,0 +1,47 @@ +import sys +import os + + +def main(): + args = sys.argv[1:] + flags = [] + addresses = [] + for item in args: + if item[0] == "-": + flags.append(item) + else: + addresses.append(item) + + outputLines = [] + for fileAddress in addresses: + try: + lines = readFileByLines(fileAddress) + for line in lines: + outputLines.append(line) + except Exception as e: + print(e) + printLines(outputLines, flags) + + +def readFileByLines(fileAddress): + file = open(fileAddress, "r", encoding="utf-8") + content = file.read() + lines = content.split("\n") + if len(lines) != 0 and lines[-1] == "": + lines.pop() + return lines + + +def printLines(outputLines, flags): + lineNumber = 1 + for line in outputLines: + if ("-n" in flags and "-b" not in flags) or ("-b" in flags and line != ""): + output = " " + str(lineNumber) + " " + line + print(output) + lineNumber += 1 + else: + print(line) + + +if __name__ == "__main__": + main() From a496168995c604b9c3ea250b6ec8fafee265134a Mon Sep 17 00:00:00 2001 From: TarasMykytiuk Date: Mon, 27 Apr 2026 22:42:57 +0300 Subject: [PATCH 2/3] ls command --- implement-shell-tools/ls/ls.py | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 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..f5539550c --- /dev/null +++ b/implement-shell-tools/ls/ls.py @@ -0,0 +1,131 @@ +import sys +import os +import pwd +import grp +import stat +from datetime import datetime +from pathlib import Path + + +def main(): + args = sys.argv[1:] + flags = [] + parentDir = ".." + currentDir = "." + path = currentDir + for item in args: + if item[0] == "-": + flags.append(item) + else: + path = item + scanResult = os.scandir(path) + isHiddenToShow = "-a" in flags + isStatsToList = "-l" in flags + content = sortDirContent(scanResult, isHiddenToShow) + + if not isHiddenToShow and not isStatsToList: + output = "" + for item in content: + output += ( + addColorToStr("\033[34m", item.name) + " " + if Path(item).is_dir() + else item.name + " " + ) + print(output) + elif isHiddenToShow and not isStatsToList: + output = ( + addColorToStr("\033[34m", currentDir) + + " " + + addColorToStr("\033[34m", parentDir) + + " " + ) + for item in content: + output += ( + addColorToStr("\033[34m", item.name) + " " + if Path(item).is_dir() + else item.name + " " + ) + print(output) + elif not isHiddenToShow and isStatsToList: + print("total " + str(calcTotalSpace(content))) + printContentStats(content) + elif isHiddenToShow and isStatsToList: + print("total " + str(calcTotalSpace(content))) + currentDirObj = Path(currentDir) + parentDirObj = Path(parentDir) + printContentStats([currentDirObj, parentDirObj]) + printContentStats(content) + + +def calcTotalSpace(content): + sum = 0 + for item in content: + sum += item.stat().st_blocks + return sum // 2 + + +def addColorToStr(color, str): + reset = "\033[0m" + return color + str + reset + + +def sortDirContent(scanResult, isHiddenToShow): + files = [] + directories = [] + hidden = [] + for item in scanResult: + if item.name[0] == ".": + hidden.append(item) + elif os.path.isfile(item): + files.append(item) + elif os.path.isdir(item): + directories.append(item) + content = files + directories + hidden if isHiddenToShow else files + directories + return content + + +def readFilePermissions(path): + permissions = os.stat(path) + perm_str = stat.filemode(permissions.st_mode) + return perm_str + + +def printContentStats(content): + for item in content: + perm = stat.filemode(item.stat().st_mode) + links = str(item.stat().st_nlink) + owner = pwd.getpwuid(item.stat().st_uid).pw_name + group = grp.getgrgid(item.stat().st_gid).gr_name + size = str(item.stat().st_size).rjust(4) + lastModTime = formatTime(item.stat().st_mtime) + itemName = str(item) if str(item) == "." else item.name + if item.is_dir(): + itemName = addColorToStr("\033[34m", itemName) + print( + perm + + " " + + links + + " " + + owner + + " " + + group + + " " + + size + + " " + + lastModTime + + " " + + itemName + ) + + +def formatTime(timestamp): + time = datetime.fromtimestamp(timestamp) + month = time.strftime("%b") # str(time.month) + day = str(time.day) + hour = str(time.hour) + minute = str(time.minute) + return month + " " + day + " " + hour.rjust(2, "0") + ":" + minute.rjust(2, "0") + + +if __name__ == "__main__": + main() From c4e42d191a5741d32e87c2157f4d404e71e2ef7a Mon Sep 17 00:00:00 2001 From: TarasMykytiuk Date: Tue, 28 Apr 2026 01:50:56 +0300 Subject: [PATCH 3/3] wc command --- implement-shell-tools/wc/wc.py | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 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..9afa5376f --- /dev/null +++ b/implement-shell-tools/wc/wc.py @@ -0,0 +1,64 @@ +import sys +import os + + +def main(): + args = sys.argv[1:] + flags = [] + addresses = [] + for item in args: + if item[0] == "-": + flags.append(item) + else: + addresses.append(item) + isLinesNumDisplay = "-l" in flags + isWordsNumDisplay = "-w" in flags + isBytesNumDisplay = "-c" in flags + isNoFlags = len(flags) == 0 + totalLines = 0 + totalWords = 0 + totalBytes = 0 + for address in addresses: + file = open(address) + fileContent = file.read() + linesNum = countFileLines(fileContent) + wordsNum = countFileWords(fileContent) + bytes = os.path.getsize(address) + totalLines += linesNum + totalWords += wordsNum + totalBytes += bytes + output = " " + if isLinesNumDisplay or isNoFlags: + output += str(linesNum) + " " + if isWordsNumDisplay or isNoFlags: + output += str(wordsNum) + " " + if isBytesNumDisplay or isNoFlags: + output += str(bytes) + " " + print(output + address) + totalOutput = " " + if isLinesNumDisplay or isNoFlags: + totalOutput += str(totalLines) + " " + if isWordsNumDisplay or isNoFlags: + totalOutput += str(totalWords) + " " + if isBytesNumDisplay or isNoFlags: + totalOutput += str(totalBytes) + " " + print(totalOutput + "total") + + +def countFileLines(fileContent): + lines = fileContent.split("\n") + linesNum = len(lines) + if lines[linesNum - 1] == "": + linesNum -= 1 + return linesNum + + +def countFileWords(fileContent): + fileContent = fileContent.replace("\n", " ") + words = fileContent.split(" ") + words = list(filter(lambda word: word != "", words)) + return len(words) + + +if __name__ == "__main__": + main()