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
87 changes: 87 additions & 0 deletions implement-shell-tools/cat/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import process from "node:process";
import { promises as fs } from "node:fs";


//one for 1 and 3
async function printOneOrMore(listOfFiles) {

Choose a reason for hiding this comment

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

Nice that all functions are generalised to work with a list, instead (one function for single file, another function is for a list)

for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");
console.log(content);
}
}


// // 2 * `cat -n sample-files/1.txt`
// async function caseTwo(oneFile) {
// const content = await fs.readFile(oneFile, "utf-8");
// const separatedToLines = content.split('\n')
// separatedToLines.forEach((line, index) => {
// console.log(`${index + 1} ${line}`)
// })
// }

// // 4 * `cat -n sample-files/*.txt`
// async function caseFour(listOfFiles) {
// for (const file of listOfFiles) {
// const content = await fs.readFile(one, "utf-8");

// const separatedToLines = content.split('\n')
// separatedToLines.forEach((line, index) => {
// console.log(`${index + 1} ${line}`)
// })
// }

// }

//one instead
// 2 * `cat -n sample-files/1.txt`
// 4 * `cat -n sample-files/*.txt`

async function caseTwoAndFour(listOfFiles) {

Choose a reason for hiding this comment

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

Overall, we do not need async/await pattern in the cat-like utility. We just sequentially read file line by line and at the same time the utility is a console utility

for (const file of listOfFiles) {

Choose a reason for hiding this comment

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

cat -n with multiple files should continue line numbering across files — i.e., if file 1 has 3 lines, file 2 starts at line 4. Currently numbering restarts at 1 per file. You'd need to track a counter outside the for loop.

const content = await fs.readFile(file, "utf-8");

const separatedToLines = content.split('\n')
separatedToLines.forEach((line, index) => {
console.log(`${index + 1} ${line}`)
})
}

}

// `cat -b sample-files/3.txt`
async function caseFive(listOfFiles) {
for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");
const separatedToLines = content.split('\n');

let countingOnlyFullLines = 1
separatedToLines.forEach((line, index) => {
if (line !== '') {
console.log(`${countingOnlyFullLines} ${line}`)
countingOnlyFullLines++
} else {
console.log('')
}

})
}

}


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

switch (argv[0]) {

Choose a reason for hiding this comment

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

What is here is "pattern matching" of the cases from the task. Whilst it work for these cases, this is unfortunately not the way how production software is written.
Several moments:

  1. functions are referring to some "cases". It is not clear what they mean. Instead, function naming should reflect what the function does: output lines, output lines with numbering etc
  2. Hint: the code in all three functions has a lot of similarities: we read list of files, traverse the list one by one, apply some rule to the line (or no rule at all) and then output the line to console. Can we generalise this somehow, like have a function whose responsibility is to traverse the input list, then the function which reads the file and applies the rules? Try it. (hint: maybe usage of functions as objects passed into initial function may help)

case '-n':
await caseTwoAndFour(argv.slice(1));
break;

case '-b':
await caseFive(argv.slice(1));
break;

default:
await printOneOrMore(argv);
break;
}
46 changes: 46 additions & 0 deletions implement-shell-tools/cat/notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import process from "node:process";
import { promises as fs } from "node:fs";
// const fs = promises

Choose a reason for hiding this comment

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

This file looks like unnecessary


// * `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`

// process.argv documentation that process.argv[0] will be the path to node
// process.argv[1] will be the path to this file
// the arguments start at index 2

const argv = process.argv.slice(2);
if (argv.length != 1) {
console.error(`Expected exactly 1 argument (a path) to be passed but got ${argv.length}.`);
process.exit(1);
}
const path = argv[0];

// const content = await fs.readFile(path, "utf-8");
// const countOfWordsContainingEs = content
// .split(" ")
// .filter((word) => word.includes("e"))
// .length;
// console.log(countOfWordsContainingEs);

// `cat sample-files/1.txt`
const content = await fs.readFile('sample-files/1.txt', "utf-8");
const contentsOfFileOne = content
console.log(contentsOfFileOne);

// * `cat -n sample-files/1.txt`
const separatedToLines = content.split('\n')
separatedToLines.forEach((line, countLine) => {
countLine+=1
console.log(line, countLine})
const withAddedCount = countFileOne.

// * `cat sample-files/*.txt`

// * `cat -n sample-files/*.txt`

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

49 changes: 49 additions & 0 deletions implement-shell-tools/ls/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// fs.readdir
import process from "node:process";
import { promises as fs } from "node:fs";


// `ls -1`
async function showAllFilesInDir(directory) {
const listOfFiles = await fs.readdir(directory);

for (const eachFile of listOfFiles) {
console.log(eachFile);
}
}

// `ls -1 sample-files`
async function showVisibleInSampleFiles() {
const listOfFiles = await fs.readdir('sample-files');

for (const eachFile of listOfFiles) {
if (eachFile[0] !== '.') {
console.log(eachFile);
}

}
}


// `ls -1 -a sample-files`
async function showAllInSampleFiles() {
const listOfFiles = await fs.readdir('sample-files');

for (const eachFile of listOfFiles) {

console.log(eachFile);

}
}



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

if (argv.includes('-a')) {
await showAllInSampleFiles();
} else if (argv.includes('sample-files')) {
await showVisibleInSampleFiles();
} else {
await showCurrentDir();

Choose a reason for hiding this comment

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

There is no such a function in this file

}
77 changes: 77 additions & 0 deletions implement-shell-tools/wc/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import process from "node:process";
import { promises as fs } from "node:fs";

//from coursework
// const content = await fs.readFile(path, "utf-8");
// const countOfWordsContainingEs = content
// .split(" ")
// .filter((word) => word.includes("e"))
// .length;
// console.log(countOfWordsContainingEs);

function countHelper(inputFiles) {

Choose a reason for hiding this comment

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

countHelper is not very clear name, could you rename so naming reflects the purpose of the function?

return {
lines: inputFiles.split('\n').length - 1,
words: inputFiles.split(' ').filter(w => w !== "").length,

Choose a reason for hiding this comment

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

It means we split only according to space, but will ignore for example newline character or other whitespace characters. Could you fix it please?

bytes: inputFiles.length,
};
}


// * `wc -l sample-files/3.txt`
// * `wc -l sample-files/*`
async function countLines(listOfFiles) {
for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");

// const linesNumbered = content.split('\n').length-1
const counts = countHelper(content);
console.log(`${counts.lines} ${file}`)
}
}

// * `wc -w sample-files/3.txt`
async function countWords(listOfFiles) {
for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");

// const wordsCounted = content.split(" ").filter(word => word !== "").length;
// console.log(`${wordsCounted} ${file}`);
const counts = countHelper(content);
console.log(`${counts.words} ${file}`);
}

}

// * `wc -c sample-files/3.txt`
async function countBytes(listOfFiles) {
for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");
// const bytesCounted = content.length;
const counts = countHelper(content);
console.log(`${counts.bytes} ${file}`);
}
}

// * `wc sample-files/*`
async function countAll(listOfFiles) {
for (const file of listOfFiles) {
const content = await fs.readFile(file, "utf-8");
const counts = countHelper(content)

console.log(`${counts.lines} ${counts.words} ${counts.bytes} ${file}`);
}
}

const argv = process.argv.slice(2);
const files = argv.filter(arg => !arg.startsWith('-'));

if (argv.includes('-l')) {
await countLines(files);
} else if (argv.includes('-w')) {
await countWords(files);
} else if (argv.includes('-c')) {
await countBytes(files);
} else {
await countAll(files);
}