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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
*/venv
10 changes: 5 additions & 5 deletions implement-shell-tools/cat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Your task is to implement your own version of `cat`.

It must act the same as `cat` would, if run from the directory containing this README.md file, for the following command lines:

* `cat sample-files/1.txt`
* `cat -n sample-files/1.txt`
* `cat sample-files/*.txt`
* `cat -n sample-files/*.txt`
* `cat -b sample-files/3.txt`
- `cat sample-files/1.txt`
- `cat -n sample-files/1.txt`
- `cat sample-files/*.txt`
- `cat -n sample-files/*.txt`
- `cat -b sample-files/3.txt`

Matching any additional behaviours or flags are optional stretch goals.

Expand Down
39 changes: 39 additions & 0 deletions implement-shell-tools/cat/my-cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env node

const fs = require("fs");

const args = process.argv.slice(2);

let numberLines = false;
let numberNonEmpty = false;
let files = [];

//Parse arguments
for (const arg of args) {
if (arg === "-n") {
numberLines = true;
} else if (arg === "-b") {
numberNonEmpty = true;
} else {
files.push(arg);
}
}

//Process each files
args.forEach((file) => {
const content = fs.readFileSync(file, "utf-8");
const lines = content.split(/\r?\n/);

let count = 1;

lines.forEach((line) => {
const shouldNumber = numberLines || (numberNonEmpty && line !== "");

if (shouldNumber) {
console.log(`${count} ${line}`);
count++;
} else {
console.log(line);
}
});
});
42 changes: 42 additions & 0 deletions implement-shell-tools/cat/my-cat.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

set -euo pipefail

number_lines=false
number_non_empty=false

# check for flags
if [ "${1:-}" = "-n" ]; then
number_lines=true
shift
elif [ "${1:-}" = "-b" ]; then
number_non_empty=true
shift
fi

count=1

# Loop through all files

for file in "$@"
do
while IFS= read -r line
do
if [ "$number_lines" = true ]; then
echo "$count $line"
count=$((count+1))

else if [ "$number_non_empty" = true ]; then
if [ -n "$line" ]; then
echo "$count $line"
count=$((count+1))
else
echo ""
fi

else
echo "$line"
fi
fi
done < "$file"
done
59 changes: 59 additions & 0 deletions implement-shell-tools/ls/my-ls.js

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When I ran ls -1 -a sample-files vs node my-ls.js -1 -a sample-files I saw slightly different output - can you check what's causing the difference?

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env node

const fs = require("node:fs");
const path = require("node:path");

function parseArgs(args) {
let showAll = false;
let targetDir = ".";

for (const arg of args) {
if (arg === "-a") {
showAll = true;
} else if (!arg.startsWith("-")) {
targetDir = arg;
}
}

return { showAll, targetDir };
}

function listDirectory(dirPath, showAll) {
let files = fs.readdirSync(dirPath);

let hidden = [];
let normal = files;

if (!showAll) {
normal = files.filter(file => !file.startsWith("."));
} else {
hidden = files.filter(file => file.startsWith("."));
normal = files.filter(file => !file.startsWith("."));

}

normal.sort();
hidden.sort();

let result = [];

if (showAll) {
result.push(".","..");
}
result.push (...normal, ...hidden);

return result;

}

function main() {
const args = process.argv.slice(2);
const { showAll, targetDir } = parseArgs(args);

const files = listDirectory(targetDir, showAll);
console.log(files.join("\n"));
}

main();


34 changes: 34 additions & 0 deletions implement-shell-tools/ls/my-ls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
set -euo pipefail

show_all=false

# handle -a
if [ "${1:-}" = "-a" ]; then
show_all=true
shift
fi

# directory (default current)
dir="."

if [ "${1:-}" != "" ]; then
dir="$1"
fi

#choose pattern
if [ "$show_all" = true ]; then
files="$dir"/.*
else
files="$dir"/*
fi
# loop
for file in $files
do
name="$(basename "$file")"

if [ "$name" = "." ] || [ "$name" = ".." ]; then
continue
fi
echo "$name"
done
83 changes: 83 additions & 0 deletions implement-shell-tools/wc/my-wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env node

const fs = require("node:fs");

function countFile(filePath) {
const stats = fs.statSync(filePath);

if (!stats.isFile()) {
console.warn(`${filePath} is not a file, skipping`);
return null;
}
const content = fs.readFileSync(filePath, "utf8");

const lines = content.split("\n").length - 1;
const words = content.trim() ? content.trim().split(/\s+/).length : 0;
const chars = Buffer.byteLength(content, "utf8");

return { lines, words, chars };
}

function main() {
const args = process.argv.slice(2);

let flags = [];
let files = [];

// 1 Parse args
for (const arg of args) {
if (arg === "-l" || arg === "-w" || arg === "-c") {
flags.push(arg);
} else {
files.push(arg);
}
}

//2 Helper function that decides what to print

function formatOutput(counts, files) {
const parts = [];

// if no flags show everything
const showAll = flags.length === 0;

if (showAll || flags.includes("-l"))parts.push(counts.lines);
if (showAll || flags.includes("-w"))parts.push(counts.words);
if (showAll || flags.includes("-c"))parts.push(counts.chars);

parts.push(files);

return parts.join(" ");
}
// 3 totals
let totalLines = 0;
let totalWords = 0;
let totalChars = 0;


// 4 per-file output
for (const file of files) {
const counts = countFile(file);
if (!counts) continue;

totalLines += counts.lines;
totalWords += counts.words;
totalChars += counts.chars;

console.log(formatOutput(counts, files));
}
// 5 Total output (only if multiple files)
if (files.length > 1) {
const totalCounts = {
lines: totalLines,
words: totalWords,
chars: totalChars,
};
console.log(formatOutput(totalCounts,"total"));
}
}

main();



45 changes: 45 additions & 0 deletions implement-shell-tools/wc/my-wc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

set -euo pipefail

flag="all"

if [ "${1:-}" = "-l" ]; then
flag="l"
shift
elif [ "${1:-}" = "-w" ]; then
flag="w"
shift
elif [ "${1:-}" = "-c" ]; then
flag="c"
shift
fi

for file in "$@"
do
if [ -d "$file" ]; then
continue
fi

lines=0
words=0
chars=0

while IFS= read -r line
do
lines=$((lines + 1))
words=$((words + $(echo "$line" | wc -w)))
chars=$((chars + ${#line} + 1))
done <"$file"

if [ "$flag" = "l" ]; then
echo "$lines $file"
elif [ "$flag" = "w" ]; then
echo "$words $file"
elif [ "$flag" = "c" ]; then
echo "$chars $file"
else
echo "$lines $words $chars $file"
fi
done