diff --git a/commands.json b/commands.json
index 74ac032..89b844e 100755
--- a/commands.json
+++ b/commands.json
@@ -83,6 +83,13 @@
         "./dist/util/interfacer.js"
       ]
     },
+    "head": {
+      "dependencies": ["vorpal-autocomplete-fs", "glob"],
+      "files": [
+        "./dist/util/interfacer.js",
+        "./dist/util/expand.js"
+      ]
+    },
     "kill": {
       "dependencies": ["fkill", "lodash"],
       "files": [
diff --git a/dist/commands/head.js b/dist/commands/head.js
old mode 100644
new mode 100755
index 54fe002..1443c73
--- a/dist/commands/head.js
+++ b/dist/commands/head.js
@@ -1,59 +1,64 @@
 'use strict';
 
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
 var interfacer = require('./../util/interfacer');
 var fs = require('fs');
 var fsAutocomplete = require('vorpal-autocomplete-fs');
 
+var expand = require('./../util/expand');
+
 var head = {
   exec: function exec(args, options) {
-    var self = this;
     options = options || {};
+    args = args || '';
+    var source = args.stdin === undefined ? 'files' : 'stdin';
 
-    options.argsType = args.stdin === undefined ? 'files' : 'stdin';
-    options.n = options.n === undefined ? 10 : options.n;
-
-    if (options.n < 1) {
-      self.log('Option n must be a positive integer.');
-      return 1;
+    var lines = options.lines ? Math.abs(options.lines) : 10;
+    if (!Number.isInteger(lines)) {
+      this.log('head: ' + options.lines + ': invalid number of lines');
+      return 0;
     }
 
-    if (options.argsType === 'stdin') {
-      self.log(head.readLines(args.stdin[0], options.n));
+    /* istanbul ignore next */
+    if (source === 'stdin') {
+      var _stdout = head.readLines(args.stdin[0], lines);
+      _stdout = _stdout.replace(/\n$/, '');
+      if (_stdout.trim() !== '') {
+        this.log(_stdout);
+      }
       return 0;
     }
 
     var files = args.files || args;
+    files = (typeof files === 'undefined' ? 'undefined' : _typeof(files)) === 'object' && files !== null && !Array.isArray(files) ? [] : files;
     files = files === undefined ? [] : files;
     files = typeof files === 'string' ? String(files).split(' ') : files;
     files = files.filter(function (arg) {
       return String(arg).trim() !== '';
     });
+    files = expand(files);
 
     var stdout = '';
-    var writeHeaders = false;
-    if (files.length > 1) {
-      writeHeaders = true;
-    }
+    var verbose = files.length > 1 && !options.silent || options.verbose;
 
-    var content = [];
     for (var i = 0; i < files.length; i++) {
       try {
-        content[i] = fs.readFileSync(files[i]).toString();
+        var content = fs.readFileSync(files[i]).toString();
+        if (verbose) {
+          stdout += (i > 0 ? '\n' : '') + '==> ' + files[i] + ' <==\n';
+        }
+        stdout += head.readLines(content, lines);
       } catch (e) {
-        self.log('head: ' + files[i] + ': No such file or directory');
-        return 1;
+        stdout += 'head: cannot open ' + files[i] + ' for reading: No such file or directory';
       }
     }
 
-    for (var i = 0; i < files.length; i++) {
-      if (writeHeaders) {
-        stdout += (i > 0 ? '\n\n' : '') + '==> ' + files[i] + ' <==\n';
-      }
-
-      stdout += head.readLines(content[i], options.n);
+    stdout = stdout.replace(/\n$/, '');
+    if (stdout.trim() !== '') {
+      this.log(stdout);
     }
 
-    self.log(stdout);
     return 0;
   },
   readLines: function readLines(content, numberOfLines) {
@@ -62,13 +67,11 @@ var head = {
     var linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines;
     for (var i = 0; i < linesToRead; i++) {
       if (stdout === '') {
-        stdout = contentArray[i];
+        stdout = contentArray[i] + '\n';
         continue;
       }
-
-      stdout += '\n' + contentArray[i];
+      stdout += contentArray[i] + '\n';
     }
-
     return stdout;
   }
 };
@@ -78,7 +81,7 @@ module.exports = function (vorpal) {
     return head;
   }
   vorpal.api.head = head;
-  vorpal.command('head [files...]').option('-n [number]', 'The first number of lines will be copied to stdout.').autocomplete(fsAutocomplete()).action(function (args, callback) {
+  vorpal.command('head [files...]').option('-n, --lines [number]', 'print the first K lines instead of the first 10').option('-q, --silent', 'Suppresses printing of headers when multiple files are being examined.').option('-v, --verbose', 'Always output headers giving file names.').autocomplete(fsAutocomplete()).action(function (args, callback) {
     args.options = args.options || {};
     return interfacer.call(this, {
       command: head,
diff --git a/dist/help.js b/dist/help.js
index 8e538ba..b3635f7 100755
--- a/dist/help.js
+++ b/dist/help.js
@@ -2,7 +2,7 @@
 
 var pad = require('./util/pad');
 
-var commands = ['alias [-p] [name=[value]]', 'cat [-AbeEnstTv] [files ...]', 'cd [dir]', 'clear', 'cp [-fnr] source ... dest', 'echo [-eE] [arg ...]', 'export [-p][id=[value]]', 'false', 'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]', 'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l', 'less [files ...]', 'ls [-aAdFhilQrRStUwx1] [paths ...]', 'mkdir [-pv] [directories ...]', 'mv [-fnv] source ... dest', 'pwd [files ...]', 'rm [-frR] [files ...]', 'sort [-chMnrR] [-o file] [files ...]', 'source filename [arguments...]', 'tail [options] <files ...>', 'touch [-acm] [-d date] [-r ref] [--time word] file ...', 'true', 'unalias [-a] name [names ...]'];
+var commands = ['alias [-p] [name=[value]]', 'cat [-AbeEnstTv] [files ...]', 'cd [dir]', 'clear', 'cp [-fnr] source ... dest', 'echo [-eE] [arg ...]', 'export [-p][id=[value]]', 'false', 'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]', 'head [-n number] [files...]', 'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l', 'less [files ...]', 'ls [-aAdFhilQrRStUwx1] [paths ...]', 'mkdir [-pv] [directories ...]', 'mv [-fnv] source ... dest', 'pwd [files ...]', 'rm [-frR] [files ...]', 'sort [-chMnrR] [-o file] [files ...]', 'source filename [arguments...]', 'tail [options] <files ...>', 'touch [-acm] [-d date] [-r ref] [--time word] file ...', 'true', 'unalias [-a] name [names ...]'];
 
 function chop(str, len) {
   var res = String(str).slice(0, len - 2);
diff --git a/package.json b/package.json
old mode 100644
new mode 100755
diff --git a/packages/cat/dist/commands/cat.js b/packages/cat/dist/commands/cat.js
index f2b1b7b..d219e51 100755
--- a/packages/cat/dist/commands/cat.js
+++ b/packages/cat/dist/commands/cat.js
@@ -91,6 +91,7 @@ var cat = {
       if (stdout.length > 0) {
         self.log(stdout.slice(0, stdout.length - 1));
       }
+
       return 0;
     } catch (e) {
       /* istanbul ignore next */
diff --git a/packages/tail/dist/commands/tail.js b/packages/tail/dist/commands/tail.js
index 6140d45..4330112 100755
--- a/packages/tail/dist/commands/tail.js
+++ b/packages/tail/dist/commands/tail.js
@@ -18,7 +18,7 @@ var tail = {
 
     var files = args;
     files = files === undefined ? [] : files;
-    files = typeof files === 'string' ? [files] : files;
+    files = typeof files === 'string' ? String(files).split(' ') : files;
     files = files.filter(function (file) {
       return String(file).trim() !== '';
     });
diff --git a/src/commands/head.js b/src/commands/head.js
old mode 100644
new mode 100755
index ac97fc2..13ef438
--- a/src/commands/head.js
+++ b/src/commands/head.js
@@ -4,55 +4,58 @@ const interfacer = require('./../util/interfacer');
 const fs = require('fs');
 const fsAutocomplete = require('vorpal-autocomplete-fs');
 
+const expand = require('./../util/expand');
+
 const head = {
 
   exec(args, options) {
-    const self = this;
     options = options || {};
+    args = args || '';
+    const source = (args.stdin === undefined) ? 'files' : 'stdin';
 
-    options.argsType = args.stdin === undefined ? 'files' : 'stdin';
-    options.n = options.n === undefined ? 10 : options.n;
-
-    if (options.n < 1) {
-      self.log('Option n must be a positive integer.');
-      return 1;
+    const lines = (options.lines) ? Math.abs(options.lines) : 10;
+    if (!Number.isInteger(lines)) {
+      this.log(`head: ${options.lines}: invalid number of lines`);
+      return 0;
     }
 
-    if (options.argsType === 'stdin') {
-      self.log(head.readLines(args.stdin[0], options.n));
+    /* istanbul ignore next */
+    if (source === 'stdin') {
+      let stdout = head.readLines(args.stdin[0], lines);
+      stdout = stdout.replace(/\n$/, '');
+      if (stdout.trim() !== '') {
+        this.log(stdout);
+      }
       return 0;
     }
 
     let files = args.files || args;
+    files = (typeof files === 'object' && files !== null && !Array.isArray(files)) ? [] : files;
     files = (files === undefined) ? [] : files;
     files = (typeof files === 'string') ? String(files).split(' ') : files;
     files = files.filter(arg => String(arg).trim() !== '');
+    files = expand(files);
 
     let stdout = '';
-    let writeHeaders = false;
-    if (files.length > 1) {
-      writeHeaders = true;
-    }
+    const verbose = ((files.length > 1 && !options.silent) || options.verbose);
 
-    const content = [];
     for (let i = 0; i < files.length; i++) {
       try {
-        content[i] = fs.readFileSync(files[i]).toString();
+        const content = fs.readFileSync(files[i]).toString();
+        if (verbose) {
+          stdout += `${i > 0 ? '\n' : ''}==> ${files[i]} <==\n`;
+        }
+        stdout += head.readLines(content, lines);
       } catch (e) {
-        self.log(`head: ${files[i]}: No such file or directory`);
-        return 1;
+        stdout += `head: cannot open ${files[i]} for reading: No such file or directory`;
       }
     }
 
-    for (let i = 0; i < files.length; i++) {
-      if (writeHeaders) {
-        stdout += `${i > 0 ? '\n\n' : ''}==> ${files[i]} <==\n`;
-      }
-
-      stdout += head.readLines(content[i], options.n);
+    stdout = stdout.replace(/\n$/, '');
+    if (stdout.trim() !== '') {
+      this.log(stdout);
     }
 
-    self.log(stdout);
     return 0;
   },
 
@@ -62,13 +65,11 @@ const head = {
     const linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines;
     for (let i = 0; i < linesToRead; i++) {
       if (stdout === '') {
-        stdout = contentArray[i];
+        stdout = `${contentArray[i]}\n`;
         continue;
       }
-
-      stdout += `\n${contentArray[i]}`;
+      stdout += `${contentArray[i]}\n`;
     }
-
     return stdout;
   }
 };
@@ -80,7 +81,9 @@ module.exports = function (vorpal) {
   vorpal.api.head = head;
   vorpal
       .command('head [files...]')
-      .option('-n [number]', 'The first number of lines will be copied to stdout.')
+      .option('-n, --lines [number]', 'print the first K lines instead of the first 10')
+      .option('-q, --silent', 'Suppresses printing of headers when multiple files are being examined.')
+      .option('-v, --verbose', 'Always output headers giving file names.')
       .autocomplete(fsAutocomplete())
       .action(function (args, callback) {
         args.options = args.options || {};
diff --git a/src/help.js b/src/help.js
index bad7978..f8c5015 100755
--- a/src/help.js
+++ b/src/help.js
@@ -12,7 +12,7 @@ const commands = [
   'export [-p][id=[value]]',
   'false',
   'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]',
-  'head [-n number] [files...]',
+  'head [-nqv] <files ...>',
   'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l',
   'less [files ...]',
   'ls [-aAdFhilQrRStUwx1] [paths ...]',
diff --git a/src/help/head.js b/src/help/head.js
old mode 100644
new mode 100755
index 478ff3d..09a0538
--- a/src/help/head.js
+++ b/src/help/head.js
@@ -1,6 +1,14 @@
 module.exports = `
-Usage: head [OPTION] [files ...]
-Show first lines of file(s).
+Usage: head [OPTION]... [FILE]...
+Print the first 10 lines of each FILE to standard output.
+With more than one FILE, precede each with a header giving the file name.
+With no FILE, or when FILE is -, read standard input.
+
+  -n, --lines <number>        output the last N lines, instead of the last 10
+  -q, --silent                suppresses printing of headers when multiple files
+                                are being examined
+  -v, --verbose               always output headers giving file names
+      --help                  display this help and exit
 
 Report head bugs to <https://github.com/dthree/cash>
 Cash home page: <http://cash.js.org/>
diff --git a/test/head.js b/test/head.js
old mode 100644
new mode 100755
index 724191f..853088c
--- a/test/head.js
+++ b/test/head.js
@@ -7,6 +7,14 @@ const cash = require('../dist/index.js');
 const $ = require('shelljs');
 require('shelljs/global');
 
+const fxt = {
+  ten: 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\n',
+  ten2: 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\n',
+  five: 'line1\nline2\nline3\nline4\nline5\n',
+  hdr1: '==> eleven.test <==\n',
+  hdr2: '==> ten.test <==\n'
+};
+
 describe('head', function () {
   before(function () {
     'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\nline11'.to('eleven.test');
@@ -17,22 +25,82 @@ describe('head', function () {
     $.rm(['eleven.test', 'ten.test']);
   });
 
-  it('should exist and be a function', function () {
+  it('should exist', function () {
     should.exist(cash.head);
   });
 
-  it('should give back ten lines when called without options', function () {
-    const result = cash.head('eleven.test');
-    result.should.be.equal('line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\n');
+  it('should print the first ten lines in file', function () {
+    const fixture = fxt.ten;
+    cash('head eleven.test').should.equal(fixture);
+  });
+
+  it('should print the first ten lines for each file with headers', function () {
+    const fixture = `${fxt.hdr1}${fxt.ten}\n${fxt.hdr2}${fxt.ten2}`;
+    cash('head *.test').should.equal(fixture);
+  });
+
+  describe('-n, --lines', function () {
+    it('should print the first five lines in file', function () {
+      const fixture = fxt.five;
+      cash('head eleven.test -n 5').should.equal(fixture);
+    });
+
+    it('should disallow an invalid number of lines', function () {
+      const fixture = `head: cows: invalid number of lines\n`;
+      cash('head eleven.test -n cows').should.equal(fixture);
+    });
   });
 
-  it('should give back five lines when called with option n set to 5', function () {
-    const result = cash.head('eleven.test', {n: 5});
-    result.should.be.equal('line1\nline2\nline3\nline4\nline5\n');
+  describe('-v, --verbose', function () {
+    it('should print the first five lines in file with header', function () {
+      const fixture = `${fxt.hdr1}${fxt.five}`;
+      cash('head eleven.test --lines 5 -v').should.equal(fixture);
+    });
+
+    it('should print the first ten lines in file with header', function () {
+      const fixture = `${fxt.hdr1}${fxt.ten}`;
+      cash('head eleven.test -v').should.equal(fixture);
+    });
+  });
+
+  describe('-q, --silent', function () {
+    it('should print the first ten lines for each file without headers', function () {
+      const fixture = `${fxt.ten}${fxt.ten2}`;
+      cash('head *.test -q').should.equal(fixture);
+    });
+  });
+
+  describe('input validation', function () {
+    it('should do nothing on undefined input', function () {
+      cash.head().should.equal('');
+    });
+
+    it('should do nothing on a blank string', function () {
+      cash.head('').should.equal('');
+    });
+
+    it('should do nothing on no params with options', function () {
+      cash('head -n 5').should.equal('');
+    });
+
+    it('should give message on an invalid file', function () {
+      const fx = `head: cannot open sss.sd for reading: No such file or directory\n`;
+      cash.head('sss.sd').should.equal(fx);
+    });
+
+    it('should continue with valid files despite invalid files', function () {
+      const fx1 = `head: cannot open sss.sd for reading: No such file or directory\n`;
+      const fx3 = `head: cannot open ddd.df for reading: No such file or directory\n`;
+      cash('head -n 5 sss.sd eleven.test ddd.df').should.equal(`${fx1}${fxt.hdr1}${fxt.five}${fx3}`);
+    });
   });
 
-  it('should write header when used with more than one file', function () {
-    const result = cash.head(['eleven.test', 'ten.test'], {n: 2});
-    result.should.be.equal('==> eleven.test <==\nline1\nline2\n\n==> ten.test <==\nline1\nline2\n');
+  describe('input piping', function () {
+    it('should work with piped input', function () {
+      cash('cat eleven.test | head -n 5');
+      // const fixture = fxt.five;
+      // vorpal bug on piping sync stdout
+      // cash('cat eleven.test | head -n 5').should.equal(fixture);
+    });
   });
 });
