## [shelljs](https://www.npmjs.com/package/shelljs)
`shelljs`模块重新包装了`child_process`,调用系统命令更加简单。
`shelljs`是`Unix Shell`在`Node.js API`层的轻量级实现,可以支持`Windows、Linux、OS X`。你可以像在`Unix`命令行敲命令一样书写代码
[TOC]
### shelljs的安装
`shelljs`是第三方模块,需要安装后才能使用。
* 全局安装
~~~
$ npm install shelljs -g
~~~
* 本地安装
将当前工作目录切换为需要使用`shelljs`模块的目录(已经创建了`package.json`文件的目录)
~~~
$ npm install shelljs --save
~~~
### shelljs的使用说明
对于熟悉`Unix Shell`脚本的开发者,简单扫一眼API就能愉快的开始写代码了。不熟悉的也没关系,`shelljs`绝大部分命令都是对文件和文件夹的操作,我们在[文件系统处理](313189)一节已经详细的将对文件系统处理相关的接口介绍了一遍,使用`fs-extra`模块处理文件系统相关的操作会简单很多,
先看个例子:
~~~
var shell = require('shelljs');
//判定git命令是否可用
if (!shell.which('git')) {
//向命令行打印git命令不可用的提示信息
shell.echo('Sorry, this script requires git');
//退出当前进程
shell.exit(1);
}
//先删除'out/Release'目录
shell.rm('-rf', 'out/Release');
//拷贝文件到'out/Release'目录
shell.cp('-R', 'stuff/', 'out/Release');
//切换当前工作目录到'lib'
shell.cd('lib');
//shell.ls('*.js')返回值是一个包含所有js文件路径的数组
shell.ls('*.js').forEach(function(file) {//遍历数组
//sed命令用于文件内容的替换,这里是对每个文件都执行如下3步操作,更改版本信息
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
//切换当前工作目录到上一层
shell.cd('..');
//同步执行git命令提交代码
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
shell.echo('Error: Git commit failed');
shell.exit(1);
}
~~~
上面的例子展示了一个可发布版本提交到`git`仓库的过程。
`shelljs`的方法都遵循:
**方法名就是我们常用的执行命令,而方法参数就是命令行参数。只是有些方法对命令行参数做了变形和拓展。**
### 重要方法介绍
#### exec()
* exec(command [, options] [, callback])
* `command <String>`:要在命令行执行的完整命令
* `options <Object>`:可选参数,JSON对象
* async: 异步执行.如果你提供了回调方法,这个值就一定为true,无论你怎么设置
* silent:打印信息不输出到命令控制台
* Node.js 的 [child_process.exec()](http://nodejs.cn/api/child_process.html#child_process_child_process_exec_command_options_callback)方法的其他参数都可以用
* ` callback:<Function>`:当进程终止时调用,并带上输出。
* `error <Error>`
* `stdout <String> | <Buffer>`
* `stderr <String> | <Buffer>`
* 返回值: 同步模式下,将返回一个ShellString(shelljs v0.6.xf返回一个形如{ code:..., stdout:... , stderr:... }的对象);异步模式下,将返回一个child_process的对象
>Note:
由于`exec()`现在同步方法的实现占用了大量`CPU`,所以,官方建议使用**异步模式**运行一个需要长时间保活的进程。
例子:
~~~
var version = exec('node --version', {silent:true}).stdout;
var child = exec('some_long_running_process', {async:true});
child.stdout.on('data', function(data) {
/* ... do something with data ... */
});
exec('some_long_running_process', function(code, stdout, stderr) {
console.log('Exit code:', code);
console.log('Program output:', stdout);
console.log('Program stderr:', stderr);
});
~~~
#### ls()
* `ls([options,] path_array)`
* `options <String>`:可选参数,可以多个参数叠加使用,比如-lA
* `-R`: 递归处理,将指定目录下的所有文件及子目录一并处理
* `-A`: 显示除影藏文件“.”和“..”以外的所有文件列表
* `-L`: 如果遇到性质为符号链接的文件或目录,直接列出该链接所指向的原始文件或目录
* `-d`: 仅显示目录名,而不显示目录下的内容列表。显示符号链接文件本身,而不显示其所指向的目录列表
* `-l`: 以长格式显示目录下的内容列表。输出的信息从左到右依次包括文件名,文件类型、权限模式、硬连接数、所有者、组、文件大小和文件的最后修改时间等
* `path_array <Array>`:可选参数,目标目录的组成的数组,ls命令依次处理各个目录
* `ls([options,] [path, ...])`
* `options <String>`:可选参数,与`ls([options,] path_array)`方法的参数一样
* ` [path, ...]`:可选参数,目标目录序列,以多参数的形式存在,
比如:ls ( path1, path2 , ... , pathN);
**ls方法返回一个包含给定的目标目录下的所有文件或目录路径集合的数组,如果没有给定路径,则默认为当前路径。如果设置了上面的提到的参数,则按照给定参数逐条将结果保存在数组中。**
例子:
~~~
ls('projs/*.js');//
ls('-R', '/users/me', '/tmp');//递归遍历'/users/me'和'/tmp'
ls('-R', ['/users/me', '/tmp']); // 和上面一条一样
ls('-l', 'file.txt'); //[ { name: 'file.txt', mode: 33188, nlink: 1, ...} ]
~~~
#### ShellString()
* ShellString(str)
* `str <String>`:常规字符串
`ShellString()`方法用于将常规字符串转换为`ShellString`。这样,就可以使用`ShellString`的方法`to()`和`toEnd()`。
#### ShellString.prototype.to(file)
**类似`Unix`命令中的*重定向操作>*,即把`ShellString`的内容覆盖写入参数指定的`file`。**
例子:
~~~
//将input.txt的内容写入outpu.txt
cat('input.txt').to('output.txt');
~~~
#### ShellString.prototype.toEnd(file)
**类似`Unix`命令中的*重定向并附加操作>>*,即把`ShellString`的内容写到指定文件的末尾。**
例子:
~~~
//将input.txt的内容附加outpu.txt的末尾
cat('input.txt').to('output.txt');
~~~
### shelljs API地址
**`shelljs`官网地址:https://www.npmjs.com/package/shelljs**