Linux's [wc] Command Cloned with node.js





5.00/5 (1 vote)
This time I implemented the wc command from Linux using node.js
Introduction
I continued the implementation of Linux commands with the help of node.js. This time, I've chosen the wc command. You can see the code below, it is a really small program. It does not have all the features which the original command has, it can do 3 basic things: counting the newlines, counting the words and counting the characters from a given file.
#!/usr/bin/env node
/*
This small node.js app should do exactly what the wc linux command does.
Quote from man wc:
Print newline, word, and byte counts for each FILE, and a total line if more than one FILE is specified. With no FILE, or when FILE is -, read standard
input. A word is a non-zero-length sequence of characters delimited by white space. The options below may be used to select which counts are printed,
always in the following order: newline, word, character, byte, maximum line length.
In this version, I will use the Commander node js extension, please see the https://github.com/visionmedia/commander.js github page.
Please use the npm install commander command to install the library in your node app folder.
*/
var fs = require('fs');
var commander = require('commander');
var NEW_LINE_DELIMITER = '\n';
var SPACE = ' ';
var TAB = '\t';
var cloneFunction = function(fn) {
// Workaround for commander.js issue.
// http://stackoverflow.com/a/6772648
return fn.bind({});
};
var checkIfFileExists = function(infile) {
var infilePath = infile.toString();
var stats = fs.statSync(infilePath);
if(!stats && !stats.isFile()) {
process.stdout.write('%s does not exist.', infilePath);
process.exit(1);
}
return infilePath;
};
var countLines = function(infile) {
var fileContent = fs.readFileSync(infile);
if(fileContent) {
var lineCount = fileContent.toString().split(NEW_LINE_DELIMITER);
if(lineCount && lineCount.length > 0) {
var numberOfLines = lineCount.length - 1;
process.stdout.write(numberOfLines + ' ' + infile + NEW_LINE_DELIMITER);
}
else {
process.stdout.write('The file is empty.');
}
}
else {
process.stdout.write('The file is empty.');
}
};
var countWords = function(infile) {
var fileContent = fs.readFileSync(infile);
if(fileContent) {
var sumOfWords = 0;
var lines = fileContent.toString().split(NEW_LINE_DELIMITER);
for(var i=0; i<lines.length ; ++i) {
if(lines[i] != NEW_LINE_DELIMITER && lines[i] != TAB && lines[i].length > 0) {
sumOfWords += (lines[i].split(SPACE)).length;
}
}
process.stdout.write(sumOfWords + ' ' + infile + NEW_LINE_DELIMITER);
}
else {
process.stdout.write('The file is empty.');
}
};
var countCharacters = function(infile) {
var fileContent = fs.readFileSync(infile);
if(fileContent) {
var textInFile = fileContent.toString();
process.stdout.write(textInFile.length + ' ' + infile + NEW_LINE_DELIMITER);
}
else {
process.stdout.write('The file is empty.');
}
};
commander.option('-l, --lines <file>', 'Path to file to analyze', cloneFunction(checkIfFileExists))
.option('-w, --words <file>', 'Path to file to analyze', cloneFunction(checkIfFileExists))
.option('-c, --characters <file>', 'Path to file to analyze', cloneFunction(checkIfFileExists))
.parse(process.argv);
if(commander.lines) {
countLines(commander.lines);
}
if(commander.words) {
countWords(commander.words);
}
if(commander.characters) {
countCharacters(commander.characters);
}
There is a method which I would like to explain more in depth: checkIfFileExists
. Here it is used in the statsync method of the node.js file system module. The statsync
method returns information(stats) about a file; these can be queried with the help of the following methods:
//
// Method names taken from: http://nodejs.org/api/fs.html#fs_class_fs_stats
//
//stats is the return value if fs.statsync(PATH_TO_FILE) method
stats.isFile();
stats.isDirectory();
stats.isBlockDevice();
stats.isCharacterDevice();
stats.isSymbolicLink(); //(only valid with fs.lstat())
stats.isFIFO();
stats.isSocket();
The code of the checkFileExists
method raises an error if there was no input passed to it, or the given path is not pointing to a file.
The countLines
function logic is simple, it reads the content of the file, and splits the string
read by the new line delimiter (under Linux, this is the "\n
").
The countWords
function does almost the same thing as the countLines
, the only difference is, after splitting the content of the file to lines with the new line delimiter, the lines' content is also split using the ' ' [SPACE] character as splitting value. After having the content of the file split based on new lines and spaces, it is easy to sum up the number of words.
The countCharacters
method is the most simple one, it reads the content of the file and returns the length of the string
.
For splitting up and working with command line arguments, I use a node js module called commander. This can be installed very easily with the classic npm
install command.
I was testing the code with few files and it seems to work ok, it gives the same results as the original wc
command. The implementation is not 100% yet, but I will try to improve it; or you can fork my github repo with these Linux command clones from the linjs repository and add some features.
Thanks for reading.