Skip to content

London | 26-SDC-Jul | Raihan Sharif | Sprint 3 | Implement shell tools - #609

Open
RaihanSharif wants to merge 28 commits into
CodeYourFuture:mainfrom
RaihanSharif:implement-shell-tools
Open

London | 26-SDC-Jul | Raihan Sharif | Sprint 3 | Implement shell tools#609
RaihanSharif wants to merge 28 commits into
CodeYourFuture:mainfrom
RaihanSharif:implement-shell-tools

Conversation

@RaihanSharif

@RaihanSharif RaihanSharif commented Jul 27, 2026

Copy link
Copy Markdown

Learners, PR Template

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

I have implemented each of the shell tools for this assignment. I have checked output against the real shell tool using the sample inputs.

My put formatting isn't EXACTLY the same as the originals, but they contain all the current information in the correct order and almost the same format.

Task ID: CYF-1150

@RaihanSharif RaihanSharif added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Jul 27, 2026

@SlideGauge SlideGauge left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice job, I got a couple of comments worth fixing, could you address them please?

// starting file number, if lines need to be prepended

for (const path of paths) {
let lineNum = 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You declare let lineNum = 1 inside the for (const path of paths) loop. When you run cat -n sample-files/*.txt against the real cat, does the numbering restart at 1 for each file, or keep climbing across all of them? Where would lineNum need to be declared to match what you see?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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...
node cat.js -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...

I don't see the difference. Other than the spacing at the start of each line.
I initally had the lineNum outside the loop so that the numbers would increment across files.
You can see this in the commit 5e36e1fccc18b08a5495f9ede132c9ed0b0cfa4b

Comment thread implement-shell-tools/cat/cat.js Outdated

if (flag === "-n") {
for (const line of lines) {
console.log(`${lineNum} ${line}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your -n output on line 48 and -b output on line 56 both use ${lineNum} ${line} — number, one space, text. Put cat -n sample-files/1.txt next to the real one: how wide is the space before the 1, and what character sits between the number and the text? You noted formatting isn't exact — is this the gap you meant, and how close could padStart plus a tab get you?

@RaihanSharif RaihanSharif Aug 2, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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...
cat % node cat.js -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...

It appears to be 5 spaces. I have added this change.

I was wrong, I will fix it again. It appears to be a padded, right justified number with total length of 6, and then tab before printing the line.

I have fixed by adding this:
console.log(`${String(lineNum).padStart(6, " ")}\t${line}`);

// returns all entries for a given path
// if -a flag, then include dotfiles, else exclude dotfiles
function getPathEntries(path, aFlag = flags.has("a")) {
let entries = fs.readdirSync(path);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Compare node ls.js -1 -a sample-files to the real ls -1 -a sample-files, line by line. Which two entries does the real one show that yours doesn't? Does the fs.readdirSync call on line 31 ever return those, and if not, where could they come from?

@RaihanSharif RaihanSharif Aug 2, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You mean this?

. 
. .

Those are current and parent directories. I figured it'd be ok to leave them out as they're not captured by process.

I've added them now.

function getPathEntries(path, aFlag = flags.has("a")) {
    let entries = fs.readdirSync(path);
    entries = [".", "..", ...entries];

    if (!aFlag) {
        entries = entries.filter((e) => !e.startsWith("."));
    }
    return entries;
}

Appears to be working as expected.

// if -a flag, then include dotfiles, else exclude dotfiles
function getPathEntries(path, aFlag = flags.has("a")) {
let entries = fs.readdirSync(path);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your output matches here, but is the order fs.readdirSync (line 31) returns entries in actually guaranteed? What does real ls do to its list before printing — and would yours still match on a machine that read the directory in a different order?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No it's not guaranteed. I made an assumption given the entries appears to be in the right order each time.

Real ls orders the path strings alphabetically before output.

I have now added a line to sort the entries.

function getPathEntries(path, aFlag = flags.has("a")) {
    let entries = fs.readdirSync(path);
    entries = [".", "..", ...entries];
    entries.sort();  // sort before output.
    if (!aFlag) {
        entries = entries.filter((e) => !e.startsWith("."));
    }
    return entries;
}

Comment thread implement-shell-tools/wc/wc.js Outdated

let fileCount = 0;
for (const path of paths) {
if (fs.statSync(path).isDirectory()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your "Is a directory" message on line 33 goes through console.log. Which stream do the real shell tools send error messages to - stdout or stderr - and does it matter if someone pipes your output into another command? (Not exercised by the sample files, just worth knowing.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for pointing this out. I have changed it now to output errors to stderr using console.error

Comment thread implement-shell-tools/wc/wc.js Outdated
@@ -0,0 +1,75 @@
import { program } from "commander";
import fs, { chownSync } from "node:fs";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What is chownSync (imported on line 2) used for in this file? And on line 58, what does the bare statement file.size; do, given file is a string? Would the program behave any differently if both were deleted?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

chownSync must have snuck in because of vs code auto imort. I don't remember putting it in there.

fs.statSync(path).size;

This is the size of the file in bytes. Doesn't matter what type of file it is.

from man wc:
-c The number of bytes in each input file is written to the standard output.

if I had done something like:

const file = fs.readFileSync(path, "utf-8");
const byteCount = file.length;

Then the byteCount would actually be a character count.

@RaihanSharif
RaihanSharif force-pushed the implement-shell-tools branch from de8dd1a to bc623a1 Compare August 2, 2026 20:47
@SlideGauge

Copy link
Copy Markdown

Nice job! Review complete!

@SlideGauge SlideGauge added Complete Volunteer to add when work is complete and all review comments have been addressed. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Complete Volunteer to add when work is complete and all review comments have been addressed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants