1
1
🌍
2
2
* [ Čeština] ( README-cs.md ) ∙ [ Ελληνικά] ( README-el.md ) ∙ [ English] ( README.md ) ∙ [ Español] ( README-es.md ) ∙ [ Français] ( README-fr.md ) ∙ [ Italiano] ( README-it.md ) ∙ [ 日本語] ( README-ja.md ) ∙ [ 한국어] ( README-ko.md ) ∙ [ Português] ( README-pt.md ) ∙ [ Русский] ( README-ru.md ) ∙ [ Slovenščina] ( README-sl.md ) ∙ [ Українська] ( README-uk.md ) ∙ [ 简体中文] ( README-zh.md ) ∙ [ 繁體中文] ( README-zh-Hant.md ) *
3
3
4
+
4
5
# 命令行的艺术
5
6
6
7
[ ![ Join the chat at https://gitter.im/jlevy/the-art-of-command-line ] ( https://badges.gitter.im/Join%20Chat.svg )] ( https://gitter.im/jlevy/the-art-of-command-line?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge )
7
8
8
- - [ 必读 ] ( #必读 )
9
+ - [ 前言 ] ( #前言 )
9
10
- [ 基础] ( #基础 )
10
11
- [ 日常使用] ( #日常使用 )
11
12
- [ 文件及数据处理] ( #文件及数据处理 )
12
13
- [ 系统调试] ( #系统调试 )
13
14
- [ 单行脚本] ( #单行脚本 )
14
15
- [ 冷门但有用] ( #冷门但有用 )
15
16
- [ 仅限 OS X 系统] ( #仅限-os-x-系统 )
17
+ - [ 仅限 Windows 系统] ( #仅限windows系统 )
16
18
- [ 更多资源] ( #更多资源 )
17
19
- [ 免责声明] ( #免责声明 )
18
- - [ 授权条款] ( #授权条款 )
19
20
20
21
21
22
![ curl -s 'https://raw.githubusercontent.com/jlevy/the-art-of-command-line/master/README.md ' | egrep -o '` \w+ ` ' | tr -d '`' | cowsay -W50] ( cowsay.png )
22
23
23
24
熟练使用命令行是一种常常被忽视,或被认为难以掌握的技能,但实际上,它会提高你作为工程师的灵活性以及生产力。本文是一份我在 Linux 上工作时,发现的一些命令行使用技巧的摘要。有些技巧非常基础,而另一些则相当复杂,甚至晦涩难懂。这篇文章并不长,但当你能够熟练掌握这里列出的所有技巧时,你就学会了很多关于命令行的东西了。
24
25
25
- 这篇文章是[ 许多作者和译者] ( AUTHORS.md ) 共同的成果。这里的大部分内容
26
+ 这篇文章是[ 许多作者和译者] ( AUTHORS.md ) 共同的成果。
27
+ 这里的部分内容
26
28
[ 首次] ( http://www.quora.com/What-are-some-lesser-known-but-useful-Unix-commands )
27
29
[ 出现] ( http://www.quora.com/What-are-the-most-useful-Swiss-army-knife-one-liners-on-Unix )
28
- 于 [ Quora] ( http://www.quora.com/What-are-some-time-saving-tips-that-every-Linux-user-should-know ) ,但考虑到这里的人们都具有学习的天赋且乐于接受别人的建议,使用 Github 来做这件事是更佳的选择。如果你在本文中发现了错误或者存在可以改善的地方,请果断提交 Issue 或 Pull Request!(当然在提交前请看一下必读节和已有的 PR/issue)。
29
-
30
+ 于 [ Quora] ( http://www.quora.com/What-are-some-time-saving-tips-that-every-Linux-user-should-know ) ,
31
+ 但已经迁移到了 Github,并由众多高手做出了许多改进。
32
+ 如果你在本文中发现了错误或者存在可以改善的地方,请[ ** 贡献你的一份力** ] ( /CONTRIBUTING.md ) 。
30
33
31
- ## 必读
34
+ ## 前言
32
35
33
36
涵盖范围:
34
37
35
38
- 这篇文章对刚接触命令行的新手以及具有命令行使用经验的人都有用处。本文致力于做到* 覆盖面广* (尽量包括一切重要的内容),* 具体* (给出最常见的具体的例子)以及* 简洁* (避免不必要的,或是可以在其他地方轻松查到的细枝末节)。每个技巧在特定情境下或是基本的,或是能显著节约时间。
36
- - 本文为 Linux 所写,除了[ 仅限 OS X 系统] ( #仅限-os-x-系统 ) 节 。其它节中的大部分内容都适用于其它 Unix 系统或 MacOS 系统 ,甚至 Cygwin。
39
+ - 本文为 Linux 所写,除了[ 仅限 OS X 系统] ( #仅限-os-x-系统 ) 和 [ 仅限 Windows 系统 ] ( #仅限windows系统 ) 的部分 。其它节中的大部分内容都适用于其它 Unix 系统或 OS X ,甚至 Cygwin。
37
40
- 本文关注于交互式 Bash,尽管很多技巧也适用于其他 shell 或 Bash 脚本。
38
41
- 本文包括了“标准的”Unix 命令和需要安装特定包的命令,只要它们足够重要。
39
42
63
66
64
67
- 学习基本的网络管理:` ip ` 或 ` ifconfig ` ,` dig ` 。
65
68
69
+ - 学习并使用一种版本控制管理系统,例如 ` git ` 。
70
+
66
71
- 熟悉正则表达式,以及 ` grep ` /` egrep ` 里不同参数的作用,例如 ` -i ` ,` -o ` ,` -v ` ,` -A ` ,` -B ` 和 ` -C ` ,这些参数是值得学习并掌握的。
67
72
68
73
- 学会使用 ` apt-get ` ,` yum ` ,` dnf ` 或 ` pacman ` (取决于你使用的 Linux 发行版)来查找或安装软件包。并确保你的环境中有 ` pip ` 来安装基于 Python 的命令行工具 (接下来提到的部分程序使用 ` pip ` 来安装会很方便)。
74
79
75
80
- 在 Bash 中,可以使用 ** ctrl-w** 删除你键入的最后一个单词,使用 ** ctrl-u** 删除整行,使用 ** alt-b** 和 ** alt-f** 以单词为单位移动光标,使用 ** ctrl-a** 将光标移至行首,使用 ** ctrl-e** 将光标移至行尾,使用 ** ctrl-k** 删除光标至行尾的所有内容,使用 ** ctrl-l** 清屏。键入 ` man readline ` 查看 Bash 中的默认快捷键,内容很多。例如 ** alt-.** 循环地移向前一个参数,以及 ** alt-*** 展开通配符。
76
81
82
+
77
83
- 你喜欢的话,可以键入 ` set -o vi ` 来使用 vi 风格的快捷键,而 ` set -o emacs ` 可以把它改回来。
78
84
79
85
- 为了方便地键入长命令,在设置你的编辑器后(例如 ` export EDITOR=vim ` ),键入 ** ctrl-x** ** ctrl-e** 会打开一个编辑器来编辑当前命令。在 vi 模式下则键入 ** escape-v** 实现相同的功能。
80
86
81
87
- 键入 ` history ` 查看命令行历史记录。其中有许多缩写,例如 ` !$ ` (最后键入的参数)和 ` !! ` (最后键入的命令),尽管通常被 ** ctrl-r** 和 ** alt-.** 取代。
82
88
89
+ - 要进入家目录可以用 ` cd ` 。要访问你的家目录中的文件,可以使用前缀 ` ~ ` (例如 ` ~/.bashrc ` )。在 ` sh ` 脚本里则用 ` $HOME ` 指代家目录。
90
+
83
91
- 回到上一个工作路径:` cd - `
84
92
85
93
- 如果你输入命令的时候改变了主意,按下 ** alt-#** 来在行首添加 ` # ` ,或者依次按下 ** ctrl-a** , ** #** , ** enter** 。这样做的话,之后你可以很方便的利用命令行历史回到你刚才输入到一半的命令。
90
98
cat hosts | xargs -I{} ssh root@{} hostname
91
99
```
92
100
101
+
93
102
- ` pstree -p ` 有助于展示进程树。
94
103
95
104
- 使用 ` pgrep ` 和 ` pkill ` 根据名字查找进程或发送信号(` -f ` 参数通常有用)。
104
113
105
114
- 使用 ` uptime ` 或 ` w ` 来查看系统已经运行多长时间。
106
115
107
- - 使用 ` alias ` 来创建常用命令的快捷形式。例如:` alias ll='ls -latr' ` 使你可以方便地执行` ls -latr ` 命令。
116
+ - 使用 ` alias ` 来创建常用命令的快捷形式。例如:` alias ll='ls -latr' ` 创建了一个新的命令别名 ` ll ` 。
117
+
118
+ - 把别名、shell 选项和常用函数保存在 ` ~/.bashrc ` ,然后[ 安排登陆 shell 来读取] ( http://superuser.com/a/183980/7106 ) 。这样你就可以在所有 shell 会话中使用你的设定。
119
+
120
+ - 把环境变量的设定以及登陆时要执行的命令保存在 ` ~/.bash_profile ` 。对于从图形界面启动的,以及 ` cron ` 工作的 shell,需要单独配置。
121
+
122
+ - 要在几台电脑中同步你的配置文件(例如 ` .bashrc ` 和 ` .bash_profile ` ),可以用 Git。
123
+
124
+ - 当变量和文件名中包含空格的时候要格外小心。Bash 变量要用引号括起来,比如 ` "FOO" ` 。尽量使用 ` -0 ` 或 ` -print0 ` 选项以便用空字符来分隔文件名,例如 ` locate -0 pattern | xargs -0 ls -al ` 或 ` find / -print0 -type d | xargs -0 ls -al ` 。如果 for 循环中循环访问的文件名含有空格,只需用 ` IFS=$'\n' ` 把内部字段分隔符设为换行符。
108
125
109
126
- 在 Bash 脚本中,使用 ` set -x ` 去调试输出,尽可能的使用严格模式,使用 ` set -e ` 令脚本在发生错误时退出而不是继续运行,使用 ` set -u ` 来检查是否使用了未赋值的变量,使用 ` set -o pipefail ` 严谨地对待错误(尽管问题可能很微妙)。当牵扯到很多脚本时,使用 ` trap ` 。一个好的习惯是在脚本文件开头这样写,这会使它检测一些错误,并在错误发生时中断程序并输出信息:
110
127
``` bash
167
184
168
185
- 以某种权限执行命令,使用` sudo ` (root 权限)或` sudo -u ` (其他用户)。使用` su ` 或者` sudo bash ` 来启动一个以对应用户权限运行的 shell。使用` su - ` 模拟其他用户的登录。
169
186
187
+ - 了解命令行的 [ 128K 限制] ( https://wiki.debian.org/CommonErrorMessages/ArgumentListTooLong ) 。使用通配符匹配大量文件名时,常会遇到“Argument list too long”的错误信息。(这种情况下换用 ` find ` 或 ` xargs ` 通常可以解决。)
188
+
189
+ - 要实现基本的计算器功能(或者一般地使用 Python),可以使用 ` python ` 解释器。例如:
190
+ ```
191
+ >>> 2+3
192
+ 5
193
+ ```
194
+
195
+
170
196
## 文件及数据处理
171
197
172
198
- 在当前路径下通过文件名定位一个文件,` find . -iname '*something*' ` (或类似的)。在所有路径下通过文件名查找文件,使用 ` locate something ` (但请记住 ` updatedb ` 可能没有对最近新建的文件建立索引)。
197
223
198
224
- 了解语言环境对许多命令行工具的微妙影响,包括排序的顺序和性能。大多数 Linux 的安装过程会将 ` LANG ` 或其他有关的变量设置为符合本地的设置。意识到当你改变语言环境时,排序的结果可能会改变。明白国际化可能会使 sort 或其他命令运行效率下降* 许多倍* 。某些情况下(例如集合运算)你可以放心的使用 ` export LC_ALL=C ` 来忽略掉国际化并使用基于字节的顺序。
199
225
226
+ - 你可以单独指定某一条命令的环境,只需在调用时把环境变量设定放在前面,例如 ` TZ=Pacific/Fiji date ` 。
227
+
200
228
- 了解 ` awk ` 和 ` sed ` 关于数据的简单处理的用法。例如,将文本文件中第三列的所有数字求和:` awk '{ x += $3 } END { print x }' ` . 这可能比同等作用的 Python 代码快三倍且代码量少三倍。
201
229
202
230
- 替换一个或多个文件中出现的字符串:
206
234
207
235
- 使用 [ ` repren ` ] ( https://github.com/jlevy/repren ) 来批量重命名,或是在多个文件中搜索替换。(有些时候 ` rename ` 命令也可以批量重命名,但要注意,它在不同 Linux 发行版中的功能并不完全一样。)
208
236
``` sh
209
- # Full rename of filenames, directories, and contents foo -> bar:
237
+ # 将文件、目录和内容全部重命名 foo -> bar:
210
238
repren --full --preserve-case --from foo --to bar .
211
- # Recover backup files whatever.bak -> whatever:
239
+ # 还原所有备份文件 whatever.bak -> whatever:
212
240
repren --renames --from ' (.*)\.bak' --to ' \1' * .bak
213
- # Same as above, using rename, if available :
241
+ # 用 rename 实现上述功能(若可用) :
214
242
rename ' s/\.bak$//' * .bak
215
243
```
216
244
217
- - 根据 man 页面的描述,` rsync ` 真的是一个快速且非常灵活的文件复制工具。它通常被用于机器间的同步,但在本地也同样有用。它同时也是删除大量文件的[ 最快方法] ( https://web.archive.org/web/20130929001850/http://linuxnote.net/jianingy/en/linux/a-fast-way-to-remove-huge-number-of-files.html ) 之一:
245
+ - 根据 man 页面的描述,` rsync ` 真的是一个快速且非常灵活的文件复制工具。它通常被用于机器间的同步,但在本地也同样有用。在安全限制允许下,用 ` rsync ` 代替 ` scp ` 可以实现续传,而不用重新从头开始。 它同时也是删除大量文件的[ 最快方法] ( https://web.archive.org/web/20130929001850/http://linuxnote.net/jianingy/en/linux/a-fast-way-to-remove-huge-number-of-files.html ) 之一:
218
246
``` sh
219
247
mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
220
248
```
@@ -244,10 +272,17 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
244
272
245
273
- 使用 ` zless ` ,` zmore ` ,` zcat ` 和 ` zgrep ` 对压缩过的文件进行操作。
246
274
275
+ - 文件属性可以通过 ` chattr ` 进行设置,它比文件权限更加底层。例如,为了保护文件不被意外删除,可以使用不可修改标记:` sudo chattr +i /critical/directory/or/file `
276
+
277
+ - 使用 ` getfacl ` 和 ` setfacl ` 以保存和恢复文件权限。例如:
278
+ ``` sh
279
+ getfacl -R /some/path > permissions.txt
280
+ setfacl --restore=permissions.txt
281
+ ```
247
282
248
283
## 系统调试
249
284
250
- - ` curl ` 和 ` curl -I ` 可以便捷地被应用于 web 调试中,它们的好兄弟 ` wget ` 也可以,或者是更潮的 [ ` httpie ` ] ( https://github.com/jakubroztocil /httpie ) 。
285
+ - ` curl ` 和 ` curl -I ` 可以便捷地被应用于 web 调试中,它们的好兄弟 ` wget ` 也可以,或者是更潮的 [ ` httpie ` ] ( https://github.com/jkbrzt /httpie ) 。
251
286
252
287
- 使用 ` iostat ` 、` netstat ` 、` top ` (` htop ` 更佳)和 ` dstat ` 去获取硬盘、cpu 和网络的状态。熟练掌握这些工具可以使你快速的对系统的当前状态有一个大概的认识。
253
288
@@ -279,12 +314,15 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
279
314
280
315
- 当调试一些之前出现的问题的时候,` sar ` 非常有用。它展示了 cpu、内存以及网络等的历史数据。
281
316
282
- - 关于更深层次的系统分析以及性能分析,看看 ` stap ` ([ SystemTap] ( https://sourceware.org/systemtap/wiki ) ),[ ` perf ` ] ( http ://en.wikipedia.org/wiki/Perf_(Linux)) ,以及[ ` sysdig ` ] ( https://github.com/draios/sysdig ) 。
317
+ - 关于更深层次的系统分析以及性能分析,看看 ` stap ` ([ SystemTap] ( https://sourceware.org/systemtap/wiki ) ),[ ` perf ` ] ( https ://en.wikipedia.org/wiki/Perf_(Linux)) ,以及[ ` sysdig ` ] ( https://github.com/draios/sysdig ) 。
283
318
284
319
- 查看你当前使用的系统,使用 ` uname ` , ` uname -a ` (Unix/kernel 信息) 或者 ` lsb_release -a ` (Linux 发行版信息)。
285
320
286
321
- 无论什么东西工作得很欢乐时试试 ` dmesg ` (可能是硬件或驱动问题)。
287
322
323
+ - 如果你删除了一个文件,但通过 ` du ` 发现没有释放预期的磁盘空间,请检查文件是否被进程占用:
324
+ ` lsof | grep deleted | grep "filename-of-my-big-file" `
325
+
288
326
289
327
## 单行脚本
290
328
@@ -299,6 +337,7 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
299
337
300
338
- 使用 ` grep . * ` (每行都会附上文件名)或者 ` head -100 * ` (每个文件有一个标题)来阅读检查目录下所有文件的内容。这在检查一个充满配置文件的目录(如 ` /sys ` 、` /proc ` 、` /etc ` )时特别好用。
301
339
340
+
302
341
- 计算文本文件第三列中所有数的和(可能比同等作用的 Python 代码快三倍且代码量少三倍):
303
342
``` sh
304
343
awk ' { x += $3 } END { print x }' myfile
@@ -314,6 +353,8 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
314
353
cat access.log | egrep -o ' acct_id=[0-9]+' | cut -d= -f2 | sort | uniq -c | sort -rn
315
354
```
316
355
356
+ - 要连续地监测变化,可以使用 ` watch ` ,例如检查某个文件夹中文件的改变,可以用 ` watch -d -n 2 'ls -rtlh | tail' ` ;或者在排查 WiFi 设置故障时要监测网络设置的更改,可以用 ` watch -d -n 2 ifconfig ` 。
357
+
317
358
- 运行这个函数从这篇文档中随机获取一条技巧(解析 Markdown 文件并抽取项目):
318
359
``` sh
319
360
function taocl() {
@@ -326,7 +367,6 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
326
367
}
327
368
```
328
369
329
-
330
370
## 冷门但有用
331
371
332
372
- ` expr ` :计算表达式或正则匹配
@@ -383,6 +423,8 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
383
423
384
424
- ` time ` :执行命令,并计算执行时间
385
425
426
+ - ` timeout ` :在指定时长范围内执行命令,并在规定时间结束后停止进程
427
+
386
428
- ` lockfile ` :使文件只能通过 ` rm -f ` 移除
387
429
388
430
- ` logrotate ` : 切换、压缩以及发送日志文件
@@ -475,33 +517,51 @@ mkdir empty && rsync -r --delete empty/ some-dir && rmdir some-dir
475
517
476
518
- ` fortune ` ,` ddate ` 和 ` sl ` :额,这主要取决于你是否认为蒸汽火车和莫名其妙的名人名言是否“有用”
477
519
520
+
478
521
## 仅限 OS X 系统
479
522
480
- 以下是* 仅限于* MacOS 系统的技巧
523
+ 以下是* 仅限于* OS X 系统的技巧
481
524
482
- - 用 ` brew ` (Homebrew)或者 ` port ` (MacPorts)进行包管理。这些可以用来在 Mac 系统上安装以上的大多数命令。
525
+ - 用 ` brew ` (Homebrew)或者 ` port ` (MacPorts)进行包管理。这些可以用来在 OS X 系统上安装以上的大多数命令。
483
526
484
527
- 用 ` pbcopy ` 复制任何命令的输出到桌面应用,用 ` pbpaste ` 粘贴输入。
485
528
486
- - 若要在 Mac OS 终端中将 Option 键视为 alt 键(例如在上面介绍的 ** alt-b** , ** alt-f** 等命令中用到),打开 偏好设置 -> 描述文件 -> 键盘 并勾选“使用 Option 键作为 Meta 键”。
529
+ - 若要在 OS X 终端中将 Option 键视为 alt 键(例如在上面介绍的 ** alt-b** , ** alt-f** 等命令中用到),打开 偏好设置 -> 描述文件 -> 键盘 并勾选“使用 Option 键作为 Meta 键”。
487
530
488
531
- 用 ` open ` 或者 ` open -a /Applications/Whatever.app ` 使用桌面应用打开文件。
489
532
490
533
- Spotlight: 用 ` mdfind ` 搜索文件,用 ` mdls ` 列出元数据(例如照片的 EXIF 信息)。
491
534
492
- - 注意 MacOS 系统是基于 BSD UNIX 的,许多命令(例如 ` ps ` ,` ls ` ,` tail ` ,` awk ` ,` sed ` )都和 Linux 中有些微的不同,这些极大的被 System V-style Unix 和 GNU 工具影响。你可以通过标题为 "BSD General Commands Manual" 的 man 页面发现这些不同。在有些情况下 GNU 版本的命令也可能被安装(例如 ` gawk ` 和 ` gsed ` 对应 GNU 中的 awk 和 sed )。如果要写跨平台的 Bash 脚本,避免使用这些命令(例如,考虑 Python 或者 ` perl ` )或者经过仔细的测试。
535
+ - 注意 OS X 系统是基于 BSD UNIX 的,许多命令(例如 ` ps ` ,` ls ` ,` tail ` ,` awk ` ,` sed ` )都和 Linux 中有些微的不同,这些极大的被 System V-style Unix 和 GNU 工具影响。你可以通过标题为 "BSD General Commands Manual" 的 man 页面发现这些不同。在有些情况下 GNU 版本的命令也可能被安装(例如 ` gawk ` 和 ` gsed ` 对应 GNU 中的 awk 和 sed )。如果要写跨平台的 Bash 脚本,避免使用这些命令(例如,考虑 Python 或者 ` perl ` )或者经过仔细的测试。
536
+
537
+ - 用 ` sw_vers ` 获取 OS X 的版本信息。
493
538
494
- - 用 ` sw_vers ` 获取 MacOS 的版本信息。
539
+ ## 仅限 Windows 系统
495
540
541
+ - 要在 Microsoft Windows 中使用 Unix shell,可以安装 [ Cygwin] ( https://cygwin.com/ ) 。本文档中介绍的大多数内容都将适用。
542
+
543
+ - 通过 Cygwin 的包管理器来安装额外的 Unix 程序。
544
+
545
+ - 使用 ` mintty ` 作为你的命令行窗口。
546
+
547
+ - 要访问 Windows 剪贴板,可以通过 ` /dev/clipboard ` 。
548
+
549
+ - 运行 ` cygstart ` 以通过默认程序打开一个文件。
550
+
551
+ - 要访问 Windows 注册表,可以使用 ` regtool ` 。
552
+
553
+ - 注意 Windows 驱动器路径 ` C:\ ` 在 Cygwin 中用 ` /cygdrive/c ` 代表,而 Cygwin 的 ` / ` 在 Windows 中显示在 ` C:\cygwin ` 。要转换 Cygwin 和 Windows 风格的路径可以用 ` cygpath ` 。这在需要调用 Windows 程序的脚本里很有用。
554
+
555
+ - 学会使用 ` wmic ` ,你就可以从命令行执行大多数 Windows 系统管理任务,并编成脚本。
496
556
497
557
## 更多资源
498
558
499
559
- [ awesome-shell] ( https://github.com/alebcay/awesome-shell ) :一份精心组织的命令行工具及资源的列表。
500
- - [ awesome-osx-command-line] ( https://github.com/herrbischoff/awesome-osx-command-line ) :一份针对 Mac OS 命令行的更深入的指南。
560
+ - [ awesome-osx-command-line] ( https://github.com/herrbischoff/awesome-osx-command-line ) :一份针对 OS X 命令行的更深入的指南。
501
561
- [ Strict mode] ( http://redsymbol.net/articles/unofficial-bash-strict-mode/ ) :为了编写更好的脚本文件。
502
562
- [ shellcheck] ( https://github.com/koalaman/shellcheck ) :一个静态 shell 脚本分析工具,本质上是 bash/sh/zsh 的 lint。
503
563
- [ Filenames and Pathnames in Shell] ( http://www.dwheeler.com/essays/filenames-in-shell.html ) :有关如何在 shell 脚本里正确处理文件名的细枝末节。
504
-
564
+ - [ Data Science at the Command Line ] ( http://datascienceatthecommandline.com/#tools ) :用于数据科学的一些命令和工具,摘自同名书籍。
505
565
506
566
## 免责声明
507
567
0 commit comments