这篇文章大部分是自 https://www.freecodecamp.org/news/command-line-for-beginners/ 翻译而来。但原创内容依然占相当大的比重,依旧遵循CC-BY-NC-SA-4.0协议,转载请同时注明本文地址和原文地址。
除非你是计算机科班出身,或者从上世纪80年代开始就使用计算机,你不太可能会有太多使用命令行的经验。然而,大多数你能找到的博客文章和在线资源在开始教你做某件事的时候都会假设你已经能熟练的使用命令行。
要成为一个命令行大师需要经过多年的实践,但这里有一个好消息:我们可以走捷径。我们并不需要知道命令行的每一个细节,而是专注熟悉最关键,最重要的基础知识。如果我们采取这个策略,我们应该能够在很短的时间内适应并开始使用命令行。
终端、控制台、命令行、Shell之间的区别
你可能听过下面这些概念:终端、控制台、命令行、Shell ,大家常把这些混为一谈,可实际上他们指的是完全不同的概念。
你可以不区分这些概念,但区分这些概念有利于你更清晰的理解命令行。所以,让我们先简要区分这些概念。
控制台(Console)
控制台是让你与电脑互动的硬件。说人话,控制台是你的电脑屏幕,鼠标以及键盘的集合。作为一名用户,你通过这些设备与你的电脑互动。
终端
终端是一个接受输入并给出输出的环境(environment)。它是一个能让我们输入计算机能够处理的命令的地方。
终端是一个程序,和你电脑上的其他程序没有区别——你可以随意安装和卸载它,也可以在你的电脑中安装许多终端,以及随时运行你想运行的终端。
所有的操作系统都安装了一个默认的终端,但有很多选择,每个都有自己的功能和特点。
Shell
Shell是一个充当命令行解释器的程序。它处理命令并输出结果。它解释和处理用户输入的命令。
与终端一样,shell是所有操作系统中默认的程序,但也可以由用户安装和卸载。
不同的Shell也有不同的语法和特点。你也可以在你的电脑上安装许多shell,并在你想的时候运行任何一个shell。
在大多数Linux和Mac操作系统中,默认的Shell是Bash,在Windows中则是Powershell。常见的Shell还有Zsh和Fish。
Shell也是一种编程语言,在这个意义上,我们可以用它建立脚本来使我们的计算机执行某种任务。脚本只不过是一系列的指令(commands),我们可以将其保存在文件中,然后在我们想要的时候执行。
关于脚本的内容我们后面再说。现在只要记住,Shell是你的计算机用来 “理解 “和执行你的命令的程序,你也可以用它来编写任务。
还要记住,终端是Shell运行的程序。但这两个程序是独立的。这意味着,我可以让任何Shell在任何终端上运行。在这个意义上,两个程序之间没有依赖性。
命令行(CLI)
CLI是一个界面,我们在其中输入命令供计算机处理。
这实际上与终端是一样的,在我看来,这两个术语可以互换使用。
CLI是Command Line Interface的缩写,所以,读作命令háng。
命令行的意义是什么?
我们刚刚提到,大多数操作系统都有一套GUI(图形用户界面)。因此,如果我们可以在屏幕上看到我们想要的信息,以及通过点击来做我们想让电脑做的事情,那么,为什么我们要背这些烦人的指令,花时间学这个烦人的终端?
第一个原因是,很多情况下,终端更高效。我们会在后文中看到一些例子:有很多任务在GUI中需要在不同的窗口中多次点击。但在命令行里,只需要一个命令就能解决。从这个意义上说,熟悉命令行将帮助你节省时间,能够更快地执行你的任务。
第二个原因是,通过在终端里输入指令,你可以轻松地将任务自动化。如前文所述,我们可以用Shell构建脚本,然后在我们想要的时候执行这些脚本。在处理那些我们不想重复做的重复性任务时,这非常有用。
例如,我们可以建立一个脚本,帮助我们每小时更换一次壁纸。或者更复杂一些,例如帮助我们自动新建一个在线仓库(repo),或者自动帮助我们在我们的云基础设施提供商那里部署一个特定的基础设施(比如VPS)。如你所见,脚本是一种节省重复性任务时间的好方法。
第三个原因是,在特定情况下,我们要使用的计算机没有GUI,只能通过命令行与之交互。例如,当你需要使用远程Linux服务器或者与你的VPS交互时。这种情况下,除了使用命令行,别无他法。因此,熟练掌握命令行能确保你能够在更多的情况下与计算机交互。
最后一个原因是它看起来很牛逼(bushi)。你见过电影里有拿着鼠标到处点的黑客吗?
来做些准备工作
当你装好了你喜爱的终端程序,或者打开了你系统自带的终端程序,整个准备工作就完成了一半。
最流行的Shell语言是Bash。当你在网上看到一个用到命令行的指南或者说明时,这个指南或者说明大概率会假设你正在使用Bash。这是大多数Linux发行版所使用的默认Shell语言。者意味着如果你使用的是Linux或Mac OS,you’re good to go。你的电脑已经在使用一种 “行业标准 “的Shell语言。
然而,如果你使用的是Windows,我知道大多数人是的,事情就变得麻烦起来,你可以参考这篇文章安装一个Windows子系统,然后做一堆杂七杂八让这个子系统用起来更加方便,这本质上是安装了一个Linux,好消息是,这并不在我们的“入门”范畴里。
最常见最有用的命令
warning 注意
如果你发现命令输入无效,大概率是因为你把文中的 ~ ,➜ ,和 $ 一并输入进了命令行。 这三个符号里,第一个表示我们当前所在的目录是用户的主文件夹,后面两个都是终端的提示,$ 的意思并不是让你输入进去,而是告诉你这行“代码”应当被输入到终端里。
这些例子将基于我目前的操作环境(Linux操作系统上的Bash)。但无论如何,大多数命令应该适用于大多数操作环境。
echo
命令会把任何传递给它的信息显示在屏幕上
echo Hello World! // Output: Hello World!
pwd
会输出终端目前打开的目录
~ pwd
/Users/l3zc
ls
输出目前文件夹里存在的内容(包括文件夹和文件),这个命令在Windows系统里是dir
。
例如,我现在想要看看我的Hexo博客文件夹下都有什么文件:
➜ ~ cd blog
➜ blog ls
_config.butterfly.yml node_modules
_config.fluid.yml package-lock.json
_config.icarus.yml package.json
_config.landscape.yml public
_config.stellar.yml scaffolds
_config.yml source
astute-window-348803-cf8da3342b4b.json theme_backup
db.json themes
firebase.json
➜ blog
如果你给ls
命令传递-a
参数,返回的内容也会包括隐藏的文件:
➜ blog ls -a
. _config.yml
.. astute-window-348803-cf8da322b.json
.DS_Store db.json
.deploy_git firebase.json
.firebase node_modules
.firebaserc package-lock.json
.github package.json
.gitignore public
_config.butterfly.yml scaffolds
_config.fluid.yml source
_config.icarus.yml theme_backup
_config.landscape.yml themes
_config.stellar.yml
cd
是Change Directory的缩写,使用这个命令可以切换目录
例如cd D:\earthdata
会终端的工作目录切换到D盘下的earthdata
文件夹。
➜ ~ cd earthdata_st
➜ earthdata_st //此时已经切换到了另一个文件夹
如果cd
后不接任何参数,无论你目前在什么工作目录下,你都会立刻回到你的主文件夹(Windows下的行为未经测试)
➜ earthdata_st cd
➜ ~
mkdir
和rmdir
分别新建文件夹和删除文件夹
例如,想要在当前工作目录下新建一个名为test
的文件夹,只需要使用mkdir test
即可,同理,想要删除当前工作目录下名为test
的文件夹,只需要使用rmdir test
。
touch
允许你新建一个空文件,例如touch test.txt
会在当前目录下新建一个名为test.txt
的空文件。
rm
允许你移除文件,例如rm test.txt
可以移除当前目录下名为test.txt
的文件。
cp
是copy的简写,cp
命令允许你复制文件,此命令接受两个参数:第一个参数是想要复制的文件/目录(文件夹),第二个则是希望复制到的位置。
例如,要在同一个目录下复制刚刚使用touch
命令新建的空文件test.txt
,我们可以使用下面的命令:
cp test.txt testCopy.txt
可以看到,目录没有改变,因为在「目的地」参数的位置上中我输入了新的文件名。
如果我想把文件复制到一个不同的目录,但保持相同的文件名,我可以输入这个命令:
cp test.txt ./testFolder/
如果我想要复制这个文件到一个不同的目录并且还改个文件名,当然可以把前两个指令综合一下:
cp test.txt ./testFolder/testCopy.txt
mv
是move的简写,mv
命令允许你把一个文件或目录从一个地方移动到另一个地方。也就是说,在一个新的目录中创建它,并在前一个目录中删除它(就像剪切和粘贴)。
mv
也接受两个参数,用法与cp
命令几乎一样,这里不再赘述。
head
允许你直接在终端里查看一个文件的开头
➜ ~ head package.json
{
"dependencies": {
"hexo-autonofollow": "^1.0.1",
"hexo-generator-baidu-sitemap": "^0.1.9",
"hexo-generator-sitemap": "^3.0.1",
"hexo-neat": "^1.0.9",
"hexo-tag-fancybox_img": "^1.0.1"
}
}
tail
与head
相对应,允许你直接在终端里查看一个文件的结尾
➜ ~ tail package.json
{
"dependencies": {
"hexo-autonofollow": "^1.0.1",
"hexo-generator-baidu-sitemap": "^0.1.9",
"hexo-generator-sitemap": "^3.0.1",
"hexo-neat": "^1.0.9",
"hexo-tag-fancybox_img": "^1.0.1"
}
}
当然,因为我的package.json
只有这些内容,head
和tail
输出的内容没有差别。
--help
参数可以被传入大多数命令,用以获得关于这个命令的帮助。如cd --help
man
是manual的缩写,可以查看一个指令的手册,例如man cd
可以查看cd
命令的手册
你甚至可以输入man bash
让控制台返回一个关于命令行的所有知识的大手册2333。
code
将打开你的默认代码编辑器。如果你不加任何参数,它会打开你最后一次打开的文件/目录
你也可以通过加参数参数来打开一个给定的文件:code test.txt
。
或者通过传递新的文件名来打开一个新的文件:code thisIsAJsFile.js
。
edit
将在你的默认命令行文本编辑器上打开文本文件(如果你在用Mac或Linux,应该是是Nano或Vim)。
现在我要问一个问题,如果你按照我说的试着用edit
打开了一个文本文件,你可以试试怎么在不关掉命令行窗口的情况下退出呢?
是不是发现退不出去?
好吧我来告诉你怎么退出去——输入:q!
(注意中英文符号的区别)然后回车。
这个梗很好笑,因为每个人一开始用命令行文本编辑器的时候都很抓瞎,因为大多数动作(比如退出编辑器)都是用键盘快捷键完成的。使用这些编辑器是另一个话题,如果你有兴趣了解更多,那就去找个教程吧。(当然,如果感兴趣的人多,我会考虑再翻译一篇文章:-))
ctrl
+c
允许你退出终端正在运行的当前进程。例如,如果你正在用npx create-react-app
创建一个react应用,并想在某个时候取消构建,只要按下ctrl
+c
,它就会停止。
- 你可以用
ctrl
+shift
+c
从终端复制文本,以及用ctrl
+shift
+v
粘贴文本到终端
clear
将清除终端里所有乱七八糟的内容,还你一个清净的终端
- 按键盘上的上键和下键,你可以查看先前的命令。
在终端里运行程序的示例
以wget
为例,几乎所有终端程序都接受参数以获取运行所必要的信息。wget
接受多个参数,每个参数之间以空格分开。
例如,要想从NASA下载Earthdata数据,需要先从NASA获取一个数据下载链接的列表,然后使用wget
的下载链接列表功能。
由于从NASA下载文件需要验证Earth Data账号,我们需要将账号和密码作为参数传递给wget
才能成功下载。
wget --load-cookies --save-cookies --auth-no-challenge=on --keep-session-cookies --user=<你的用户名> --ask-password -i <链接列表文件的位置>
在终端中,一个”-“只能传递短的参数名称,例如-t
,-h
,两个-可以传递长参数名称,例如--load-cookies
。下面是这个命令里部分参数的意义:
参数 | 意义 |
---|---|
–load-cookies | 加载cookies |
–ask-password | 当需要密码时询问 |
-i | 下载列表 |
一般情况下无需掌握所有需要的参数,需要使用某个功能时可以通过查看该程序的文档获得相应的帮助。