命令行速成课程

在你的开发过程中,你无疑需要在终端(或“命令行”——它们实际上是一样的)中运行一些命令。本文提供了终端入门指南,包括你需要输入的基本命令、如何将命令链接在一起以及如何添加自己的命令行界面 (CLI) 工具。

先决条件 熟悉核心 HTMLCSSJavaScript 语言。
目标 了解终端/命令行是什么,应该学习哪些基本命令以及如何安装新的命令行工具。

欢迎来到终端

终端是用于执行基于文本的程序的文本界面。如果你正在运行任何用于 Web 开发的工具,那么几乎可以肯定你需要打开命令行并运行一些命令来使用你选择的工具(你经常会看到这样的工具被称为CLI 工具——命令行界面工具)。

大量工具可以通过在命令行中输入命令来使用;许多工具预装在你的系统上,还有大量其他工具可以从软件包注册中心安装。软件包注册中心就像应用商店,但(主要)用于基于命令行的工具和软件。我们将在本章后面了解如何安装一些工具,并在下一章中详细了解软件包注册中心。

命令行最大的批评之一是它在用户体验方面严重不足。第一次查看命令行可能会令人望而生畏:一个空白屏幕和一个闪烁的光标,几乎没有明显的帮助信息告诉你该做什么。

表面上看,它们远非友好,但你可以用它们做很多事情,我们保证,只要有一点指导和练习,使用它们就会变得更容易!这就是我们提供本章的原因——帮助你在这个看似不友好的环境中入门。

终端的起源是什么?

终端起源于 20 世纪 50 年代到 60 年代,其最初的形式与我们今天使用的完全不同(对此我们应该心存感激)。你可以在维基百科的 计算机终端 词条中阅读一些历史信息。

从那时起,终端一直是所有操作系统的恒定特征——从桌面机器到隐藏在云中的服务器,再到像 Raspberry PI Zero 这样的微型计算机,甚至到手机。它提供了对计算机底层文件系统和低级功能的直接访问,因此如果你知道自己在做什么,它对于快速执行复杂任务非常有用。

它也适用于自动化——例如,编写一个命令来立即更新数百个文件的标题,比如从“ch01-xxxx.png”更改为“ch02-xxxx.png”。如果你使用 Finder 或 Explorer GUI 应用程序更新文件名,则需要花费很长时间。

无论如何,终端在不久的将来都不会消失。

终端是什么样子的?

下面你可以看到一些可用的不同类型的程序,它们可以让你进入终端。

下一张图片显示了 Windows 中可用的命令提示符——从“cmd”程序到“powershell”都有很多选项——可以通过在开始菜单中输入程序名称来运行。

A vanilla windows cmd line window, and a windows powershell window

下面,你可以看到 macOS 终端应用程序。

A basic vanilla macOS terminal

如何访问终端?

如今许多开发人员都在使用基于 Unix 的工具(例如终端以及你可以通过它访问的工具)。当今网络上存在的许多教程和工具都支持(并且遗憾地假设)基于 Unix 的系统,但不用担心——它们在大多数系统上都可用。在本节中,我们将了解如何在您选择的系统上访问终端。

Linux/Unix

如上所述,Linux/Unix 系统默认提供了一个终端,列在你的应用程序中。

macOS

macOS 有一个名为 Darwin 的系统位于图形用户界面之下。Darwin 是一个类 Unix 系统,它提供终端以及对低级工具的访问。macOS Darwin 与 Unix 大致相同,在我们阅读本文时,它足够好,不会让我们有任何顾虑。

终端在 macOS 上位于 Applications/Utilities/Terminal。

Windows

与其他一些编程工具一样,在 Windows 上使用终端(或命令行)传统上不如其他操作系统那样简单或容易。但情况正在好转。

长期以来,Windows 一直有自己的类似终端的程序,称为 cmd(“命令提示符”),但它绝对与 Unix 命令不兼容,相当于旧式的 Windows DOS 提示符。

有一些更好的程序可以在 Windows 上提供终端体验,例如 Powershell(点击此处查找安装程序)和 Gitbash(它是 git for Windows 工具集的一部分)。

但是,在现代 Windows 中最好的选择是 Windows 子系统 Linux (WSL)——一个用于直接在 Windows 10 内部运行 Linux 操作系统的兼容性层,允许你直接在 Windows 上运行“真正的终端”,而无需虚拟机。

可以从 Windows 应用商店免费直接安装。你可以在 Windows 子系统 Linux 文档 中找到所需的所有文档。

a screenshot of the Windows subsystem for Linux documentation

在 Windows 上选择哪个选项方面,我们强烈建议尝试安装 WSL。你可以坚持使用默认的命令提示符 (cmd),许多工具都可以正常工作,但如果你与 Unix 工具具有更好的兼容性,你会发现一切都会更容易。

旁注:命令行和终端有什么区别?

通常,你会发现这两个术语可以互换使用。从技术上讲,终端是启动并连接到 shell 的软件。shell 是你的会话和会话环境(提示符和快捷方式可能在其中自定义)。命令行是输入命令并闪烁光标的文字行。

你必须使用终端吗?

尽管命令行提供了大量工具,但如果你使用的是像 Visual Studio Code 这样的工具,那么也有一大堆扩展可以用作代理来使用终端命令,而无需直接使用终端。但是,你不会为你想做的所有事情都找到代码编辑器扩展——你最终必须获得一些终端的使用经验。

基本的内置终端命令

闲话少说——让我们开始了解一些终端命令!默认情况下,命令行可以执行以下几件事,以及每种情况下相关工具的名称

  • 浏览计算机的文件系统以及创建、复制、重命名和删除等基本级任务
    • 在目录结构中移动:cd
    • 创建目录:mkdir
    • 创建文件(并修改其元数据):touch
    • 复制文件或目录:cp
    • 移动文件或目录:mv
    • 删除文件或目录:rm
  • 下载特定 URL 中找到的文件:curl
  • 搜索较大体积文本中的文本片段:grep
  • 逐页查看文件内容:lesscat
  • 操作和转换文本流(例如将 HTML 文件中的所有 <div> 实例更改为 <article>):awktrsed

注意:网上有很多优秀的教程深入讲解命令行——这只是一个简要介绍!

让我们继续前进,看看如何在命令行上使用其中一些工具。在你继续操作之前,请打开你的终端程序!

当你访问命令行时,你不可避免地需要导航到特定的目录以“执行某些操作”。所有操作系统(假设默认设置)都将在你的“主目录”中启动其终端程序,然后你可能希望移动到其他位置。

cd 命令允许你更改目录。从技术上讲,cd 不是程序,而是内置命令。这意味着你的操作系统开箱即用地提供它,并且你也不会意外地删除它——谢天谢地!你不需要太担心命令是内置的还是不是,但请记住,内置命令出现在所有基于 unix 的系统上。

要更改目录,请在终端中输入 cd,后跟你要移动到的目录。假设该目录位于你的主目录内,你可以使用 cd Desktop(请参阅下面的屏幕截图)。

results of the cd Desktop command being run in a variety of windows terminals - the terminal location moves into the desktop

尝试在你的系统终端中输入此命令

bash
cd Desktop

如果你想返回到上一个目录,可以使用两个点

bash
cd ..

注意:一个非常有用的终端快捷方式是使用 tab 键自动完成你已知的名称,而不是必须全部输入。例如,在输入上述两个命令后,尝试输入 cd D 并按 tab——它应该为你自动完成目录名 Desktop,前提是它存在于当前目录中。在你继续操作时请记住这一点。

如果你要转到的目录嵌套得很深,你需要知道到达它的路径。随着你对文件系统结构越来越熟悉,这通常会变得更容易,但如果你不确定路径,你通常可以通过结合使用 ls 命令(见下文)以及在 Explorer/Finder 窗口中四处点击来查看目录相对于你当前位置的位置来弄清楚。

例如,如果你想转到名为 src 的目录,该目录位于名为 project 的目录内,位于 Desktop 上,你可以输入以下三个命令从你的主文件夹到达那里

bash
cd Desktop
cd project
cd src

但这是一种浪费时间的方法——相反,你可以输入一个命令,路径中的不同项目用正斜杠分隔,就像你在 CSS、HTML 或 JavaScript 代码中指定图像或其他资源的路径时一样

bash
cd Desktop/project/src

请注意,在你的路径上包含一个前导斜杠会使路径成为绝对路径,例如 /Users/your-user-name/Desktop。像上面那样省略前导斜杠会使路径相对于你当前的工作目录。这与你在 Web 浏览器中看到的 URL 完全相同。前导斜杠表示“在网站的根目录下”,而省略斜杠表示“URL 相对于我的当前页面”。

注意:在 Windows 上,你使用反斜杠而不是正斜杠,例如 cd Desktop\project\src——这可能看起来很奇怪,但如果你想知道原因,请 观看这段 YouTube 视频,其中包含微软首席工程师的解释。

列出目录内容

另一个内置的 Unix 命令是 ls(代表列表),它列出你当前所在目录的内容。请注意,如果你使用的是默认的 Windows 命令提示符 (cmd),则此命令将不起作用——等效命令为 dir

现在尝试在你的终端中运行此命令

bash
ls

这会为你提供当前工作目录中文件和目录的列表,但信息非常基础——你只会获得每个项目的名称,而不是它是否是文件或目录,或其他任何信息。幸运的是,对命令用法进行少量更改可以提供更多信息。

介绍命令选项

大多数终端命令都有选项——这些是添加到命令末尾的修饰符,使命令的行为略有不同。这些通常由命令名称后面的空格、破折号以及一个或多个字母组成。

例如,试试这个命令,看看你得到了什么

bash
ls -l

对于ls命令,-l(读作dash ell)选项可以让你以每行一个文件或目录的方式显示列表,并提供更多信息。可以通过查看每行最左侧的字母“d”来识别目录。这些就是我们可以使用cd命令进入的目录。

下面是一个截图,上面是“原始”的macOS终端,下面是一个自定义的终端,添加了一些额外的图标和颜色,使其看起来更生动——两者都显示了运行ls -l的结果。

A vanilla macOS terminal and a more colorful custom macOS terminal, showing a file listing - the result of running the ls -l command

注意:要了解每个命令都有哪些可用选项,可以查看其手册页。可以通过键入man命令,然后跟着要查找的命令名称来实现,例如man ls。这将在终端的默认文本文件查看器(例如,在我的终端中是less)中打开手册页,然后你就可以使用方向键或类似的机制滚动浏览页面。手册页详细列出了所有选项,一开始可能会有点吓人,但至少你知道在需要时它就在那里。浏览完手册页后,需要使用文本查看器的退出命令退出(在less中是“q”;如果不太清楚,可能需要在网上搜索)。

注意:要同时使用多个选项运行命令,通常可以将它们全部放在连字符后面的单个字符串中,例如ls -lahls -ltrh。尝试查看ls手册页来了解这些额外选项的作用!

现在我们已经讨论了两个基本命令,在你的目录中四处看看,看看是否可以从一个地方导航到另一个地方。

创建、复制、移动、删除

还有许多其他基本的实用程序命令,在使用终端时你可能会经常用到它们。它们非常简单,所以我们不会像前面几个命令那样详细解释它们。

在一个你创建的测试目录中试用它们,这样你就不会意外删除任何重要的东西,使用下面的示例命令作为指导。

  • mkdir——在当前目录中创建一个新的目录,其名称是在命令名称后面提供的。例如,mkdir my-awesome-website将创建一个名为my-awesome-website的新目录。
  • rmdir——删除指定的目录,但前提是该目录为空。例如,rmdir my-awesome-website将删除我们上面创建的目录。如果你想删除一个非空目录(并删除它包含的所有内容),则可以使用rm -r代替(见下文),但这很危险。确保目录中没有任何你以后可能需要的东西,因为它将永远消失。
  • touch——在当前目录中创建一个新的空文件。例如,touch mdn-example.md创建一个名为mdn-example.md的新空文件。
  • mv——将文件从第一个指定的文件位置移动到第二个指定的文件位置,例如mv mdn-example.md mdn-example.txt(位置以文件路径的形式写出)。此命令将当前目录中名为mdn-example.md的文件移动到当前目录中名为mdn-example.txt的文件。从技术上讲,文件正在被移动,但从实际角度来看,此命令实际上是在重命名文件。
  • cp——与mv类似,cp在第二个指定位置创建第一个指定位置文件的副本。例如,cp mdn-example.txt mdn-example.txt.bak创建了一个名为mdn-example.txt.bakmdn-example.txt副本(当然,你也可以根据需要将其命名为其他名称)。
  • rm——删除指定的文件。例如,rm mdn-example.txt删除一个名为mdn-example.txt的单个文件。请注意,此删除是永久性的,无法通过桌面用户界面上的回收站撤消。

注意:许多终端命令允许你使用星号作为“通配符”字符,表示“任意字符序列”。这允许你对可能数量很大的文件同时运行操作,所有这些文件都匹配指定的模式。例如,rm mdn-*将删除所有以mdn-开头的文件。rm mdn-*.bak将删除所有以mdn-开头并以.bak结尾的文件。

终端 - 有害吗?

我们之前已经提到了这一点,但为了明确起见——在使用终端时需要小心。简单的命令不会带来太多危险,但当你开始组合更复杂的命令时,需要仔细考虑命令将执行的操作,并在最终在目标目录中运行它们之前先进行测试。

假设你在一个目录中有1000个文本文件,并且想要遍历所有这些文件,只删除文件名中包含特定子字符串的文件。如果不小心,你可能会最终删除一些重要的东西,从而丢失大量工作。一个好的习惯是在文本编辑器中写出你的终端命令,弄清楚你认为它应该是什么样子,然后备份你的目录,并在备份上先运行该命令进行测试。

另一个好建议——如果你不习惯在自己的机器上尝试终端命令,一个安全的地方是在Glitch.com上尝试。除了是一个尝试 Web 开发代码的好地方之外,这些项目还允许你访问终端,因此你可以在该终端中直接运行所有这些命令,并确信不会破坏自己的机器。

a double screenshot showing the glitch.com home page, and the glitch terminal emulator

获取特定终端命令快速概述的一个很好的资源是tldr.sh。这是一个由社区驱动的文档服务,类似于MDN,但专门针对终端命令。

在下一节中,让我们更上一层楼(实际上是几层楼),看看如何将工具连接到命令行上,真正了解终端相对于常规桌面用户界面的优势。

使用管道连接命令

当你开始使用|(管道)符号将命令链接在一起时,终端就会真正发挥其作用。让我们快速了解一下这意味着什么。

我们已经了解了ls,它输出当前目录的内容。

bash
ls

但是如果我们想快速计算当前目录中文件和目录的数量呢?ls本身无法做到这一点。

还有一个名为wc的Unix工具可用。它可以计算输入到其中的单词、行、字符或字节的数量。这可以是一个文本文件——下面的示例输出myfile.txt中的行数。

bash
wc -l myfile.txt

但它也可以计算管道输入的任何输出的行数。例如,以下命令计算ls命令输出的行数(如果单独运行,它通常会打印到终端),并将该计数输出到终端。

bash
ls | wc -l

由于ls在单独的行上打印每个文件或目录,因此这实际上为我们提供了目录和文件计数。

那么这里发生了什么呢?(Unix)命令行工具的一般理念是它们将文本打印到终端(也称为“打印到标准输出”或STDOUT)。很多命令还可以从流式输入(称为“标准输入”或STDIN)读取内容。

管道运算符可以将这些输入和输出连接在一起,允许我们构建越来越复杂的运算以满足我们的需求——一个命令的输出可以成为下一个命令的输入。在本例中,ls通常会将其输出打印到STDOUT,但ls的输出被管道输送到wcwc将该输出作为输入,计算它包含的行数,并将该计数打印到STDOUT

稍微复杂一点的示例

让我们来看一些更复杂的内容。

我们首先尝试使用curl命令(它可以用来从URL请求内容)从https://mdn.org.cn/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch获取MDN的“fetch”页面的内容。现在就试试吧。

bash
curl https://mdn.org.cn/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

你不会得到任何输出,因为页面已被重定向(到/Web/API/fetch)。我们需要使用-L标志明确告诉curl跟随重定向。

让我们也看看developer.mozilla.org使用curl-I标志返回的标头,并将它发送到终端的所有位置重定向打印出来,方法是将curl的输出管道输送到grep(我们将要求grep返回所有包含“location”一词的行)。

尝试运行以下命令(你会看到在到达最终页面之前只有一个重定向)。

bash
curl https://mdn.org.cn/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch -L -I | grep location

你的输出应该如下所示(curl首先会输出一些下载计数器等)。

bash
location: /en-US/docs/Web/API/fetch

虽然是人为设计的,但我们可以更进一步,转换location:行的内容,在每个内容的开头添加基本来源,以便我们获得打印出的完整URL。为此,我们将添加awk(这是一种类似于JavaScript、Ruby或Python的编程语言,只是历史更悠久!)。

尝试运行此命令。

bash
curl https://mdn.org.cn/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch -L -I | grep location | awk '{ print "https://mdn.org.cn" $2 }'

你的最终输出应该如下所示。

bash
https://mdn.org.cn/en-US/docs/Web/API/fetch

通过组合这些命令,我们自定义了输出以显示当我们请求/docs/Web/API/WindowOrWorkerGlobalScope/fetch URL时Mozilla服务器重定向的完整URL。了解你的系统在未来几年将证明非常有用——学习这些单用途工具的工作原理以及它们如何成为你解决利基问题的工具箱的一部分。

添加增强功能

现在我们已经了解了系统自带的一些内置命令,让我们看看如何安装第三方CLI工具并使用它。

目前,用于前端 Web 开发的大量可安装工具生态系统主要存在于npm中,这是一个私有的软件包托管服务,与Node.js紧密合作。这种情况正在缓慢扩展——随着时间的推移,你可能会看到更多软件包提供商。

安装Node.js还会安装npm命令行工具(以及一个补充的以npm为中心的工具npx),它提供了一个安装其他命令行工具的途径。Node.js和npm在所有系统中都相同:macOS、Windows和Linux。

现在在你的系统上安装npm,方法是访问上面的URL并下载并运行适合你操作系统的Node.js安装程序。如果出现提示,请确保将npm包含在安装中。

the Node.js installer on windows, showing the option to include npm

虽然我们将在接下来的文章中介绍许多不同的工具,但我们将先学习Prettier。Prettier是一个有主见的代码格式化程序,它只有“几个选项”。选项越少,往往意味着越简单。考虑到工具有时在复杂性方面会失控,“几个选项”可能非常有吸引力。

在哪里安装我们的CLI工具?

在我们深入安装Prettier之前,有一个问题需要回答——“我们应该在哪里安装它?”

使用npm,我们可以选择全局安装工具——这样我们就可以在任何地方访问它们——或者在当前项目目录中本地安装。

全局安装和本地安装各有优缺点——以下列出的全局安装的优缺点远非详尽无遗。

全局安装的优点

  • 在终端的任何位置都可以访问
  • 只需安装一次
  • 占用更少的磁盘空间
  • 始终使用相同的版本
  • 感觉就像任何其他 Unix 命令

全局安装的缺点

  • 可能与项目的代码库不兼容
  • 团队中的其他开发人员无法访问这些工具,例如,如果通过 Git 等工具共享代码库。
  • 与前一点相关,它使项目代码更难复制(如果在本地安装工具,则可以将其设置为依赖项并使用npm install安装)。

虽然“缺点”列表较短,但全局安装的负面影响可能远大于其带来的好处。在这里,我们将进行本地安装,但如果您了解了相关的风险,也可以随时进行全局安装。

安装 Prettier

Prettier 是一款针对前端开发人员的代码格式化工具,它专注于基于 JavaScript 的语言,并添加了对 HTML、CSS、SCSS、JSON 等的支持。

Prettier 可以

  • 节省手动确保所有代码文件样式一致的认知开销;Prettier 可以自动完成此操作。
  • 帮助 Web 开发新手以最佳实践的方式格式化代码。
  • 安装在任何操作系统上,甚至可以作为项目工具的直接一部分,确保与您一起处理代码的同事和朋友使用您正在使用的代码风格。
  • 可以配置为在保存时、键入时甚至发布代码之前运行(使用稍后在模块中看到的其他工具)。

在本文中,我们将按照Prettier 安装指南的建议,在本地安装 Prettier。

安装好 Node 后,打开终端并运行以下命令来安装 Prettier(我们将在下一篇文章中解释--save-dev的作用)

bash
npm install --save-dev prettier

您现在可以使用npx工具在本地运行该文件。与许多其他命令一样,不带任何参数运行该命令将提供用法和帮助信息。现在试试看

bash
npx prettier

您的输出应该类似于以下内容

bash
Usage: prettier [options] [file/glob ...]

By default, output is written to stdout.
Stdin is read if it is piped to Prettier and no files are given.

…

即使用法信息很长,也始终值得至少浏览一下。这将有助于您更好地理解工具的预期使用方式。

注意:如果您尚未在本地安装 Prettier,则运行npx prettier将下载并运行最新版本的 Prettier,仅用于该命令。虽然这听起来很棒,但新版本的 Prettier 可能会稍微修改输出。您需要在本地安装它,以便您修复正在使用的 Prettier 版本以进行格式化,直到您准备好更改它为止。

使用 Prettier

让我们快速体验一下 Prettier,以便您了解它的工作原理。

首先,在文件系统上的某个易于查找的位置创建一个新目录。也许在您的桌面上创建一个名为prettier-test的目录。

现在将以下代码保存在测试目录内的名为index.js的新文件中

js
const myObj = {
a:1,b:{c:2}}
function printMe(obj){console.log(obj.b.c)}
printMe(myObj)

我们可以对代码库运行 Prettier 以检查我们的代码是否需要调整。cd到您的目录,然后尝试运行此命令

bash
npx prettier --check index.js

您应该得到类似以下内容的输出

bash
Checking formatting...
index.js
Code style issues found in the above file(s). Forgot to run Prettier?

因此,有一些代码样式可以修复。没问题。将--write选项添加到prettier命令将修复这些问题,让我们专注于编写有用的代码。

现在尝试运行此版本的命令

bash
npx prettier --write index.js

您将获得如下输出

bash
Checking formatting...
index.js
Code style issues fixed in the above file(s).

但更重要的是,如果您查看 JavaScript 文件,您会发现它已被重新格式化为类似以下内容

js
const myObj = {
  a: 1,
  b: { c: 2 },
};
function printMe(obj) {
  console.log(obj.b.c);
}
printMe(myObj);

根据您的工作流程(或您选择的工作流程),您可以将其作为流程的自动化部分。自动化确实是工具的优势所在;我们个人偏好的是无需配置任何内容即可“自动完成”的自动化。

对于 Prettier,可以通过多种方式实现自动化,尽管这些内容超出了本文的范围,但网上有一些优秀的资源可以提供帮助(其中一些已链接)。您可以调用 Prettier

  • 在使用Husky将代码提交到 Git 存储库之前。
  • 无论何时在代码编辑器中点击“保存”,无论是VS Code还是Sublime Text
  • 作为使用GitHub Actions等工具进行持续集成检查的一部分。

我们个人更喜欢第二个选项——在使用 VS Code 时,Prettier 会启动并清理每次我们点击保存时需要进行的任何格式化。您可以在Prettier 文档中找到更多关于以不同方式使用 Prettier 的信息。

其他可玩工具

如果您想尝试一些其他工具,以下是一些有趣的工具列表

  • bat——一个“更友好的”catcat用于打印文件内容)。
  • prettyping——命令行上的ping,但可视化(ping是一个用于检查服务器是否响应的有用工具)。
  • htop——一个进程查看器,当某些东西导致您的 CPU 风扇像喷气发动机一样工作并且您想识别有问题的程序时很有用。
  • tldr——在本章前面提到过,但也可以作为命令行工具使用。

请注意,上述某些建议可能需要使用 npm 进行安装,就像我们对 Prettier 所做的那样。

总结

这标志着我们对终端/命令行的简短之旅的结束。接下来,我们将更详细地了解包管理器以及我们可以用它们做什么。