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
var fs = require('fs');
var commander = require('commander');
var NEW_LINE_DELIMITER = '\n';
var SPACE = ' ';
var TAB = '\t';
var cloneFunction = function(fn) {
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:
stats.isFile();
stats.isDirectory();
stats.isBlockDevice();
stats.isCharacterDevice();
stats.isSymbolicLink();
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.
CodeProject