发现终端 发现终端

2025-06-08

发现终端

发现终端

最初发表在我的博客上。

目录

发现终端

当人们想象程序员时,他们通常会想象
一个人坐在电脑屏幕前,屏幕上
飞快地显示着难以辨认的文本流,就像《黑客帝国》里那样。让我们来澄清
一下。这并非事实,至少在大多数情况下并非如此。
然而,《黑客帝国》也有一些地方是对的。程序员的工作是代码
顾名思义,必须先学习才能理解
。任何不熟悉读写代码的人
只会看到乱码。这些电影通常也
对程序员在终端中输入命令这一事实做出了正确的描述。

什么是终端?

人们日常使用的大多数应用程序都具有图形用户界面 (GUI)。想想 Photoshop、
Firefox 或您的智能手机应用程序。这些应用程序功能强大,但用户通常 首先
受限于其中实现的功能。如果您突然想使用 Photoshop 中某个新功能,而该功能尚未提供,该怎么办?您可能最终 要么等待最新版本发布,要么不得不 安装另一个应用程序。



然而,程序员工具箱中最重要的工具之一却属于
另一种类型。它被称为终端,它是一个命令行应用程序。也就是说,你
输入一个命令,你的计算机就会执行该命令,并
在终端中显示输出。

换句话说,这是一款你可以向计算机发出
指令的应用程序。如果你知道如何发出指令,你的计算机会很乐意服从。
但是,如果你命令它做一些愚蠢的事情,它也会服从。

— 你:“计算机,创建该文件夹。”

— 计算机:“当然。”

— 您:“现在将桌面上的所有文件放入该新文件夹中。”

— 计算机:“没问题。”

— 你:“现在永久删除该文件夹以及里面的所有内容。”

— 计算机:“完成。”

— 你:“等等,不,我的错误,我要把它拿回来。”

— 计算机:“抱歉,正如您所要求的,它已经全部消失了。”

- 你: ”…”

— 计算机:“我一点也不抱歉。”

这句名言再正确不过了:

能力越大,责任越大

学习使用终端确实会彻底改变你与计算机的交互方式。 终端
不再局限于应用程序,而是让你可以自由无限制地 访问计算机的各个部分。你不再受制于有限的命令数量,而是 会受到已知命令数量的限制。因此, 学习如何使用终端将帮助你深入了解 计算机的工作原理。让我们看看能做些什么。我们从小处着手,但相信 我,它会越来越好。





你的第一步

首先,让我们定义几个词。

终端是一个可以在计算机上打开的应用程序,
您可以在其中通过命令行界面 (CLI) 输入命令。当
您按下Enter键盘上的某个键时,shell 会执行该命令
,并将结果显示在终端中。

在计算机发展的早期,视频终端是实际的物理设备,用于在可能占据 整个房间的
远程计算机上执行命令。

DEC VT100,一款可追溯至 1978 年的物理视频终端
DEC VT100,一款可追溯至 1978 年的物理视频终端

如今,终端是在图形窗口中运行的程序,模拟
旧视频终端的行为。

这就是现在的终端的样子
现在的终端就是这个样子的。

不同的操作系统
预装了不同的终端和不同的 shell,但最常见的 shell 肯定是bash

在深入探讨之前,我们先打开一个终端!具体操作取决于你的操作系统。

打开终端

在 MacOS 上

打开Finder应用程序,点击Applications左侧窗格中的 ,然后
进入Utilities目录,执行Terminal应用程序。您也可以通过点击 屏幕右上角的
放大镜图标(或使用键盘快捷键)来使用 Spotlight 搜索,然后输入
Cmd
SpaceTerminal

在 Linux 上

根据您使用的 Linux 发行版,它可能预装了 XTerm、
Gnome-Terminal 或 Konsole。请在您的应用程序菜单中查找这些程序
。许多 Linux 安装使用
Ctrl- Alt-T键盘快捷键来
打开终端窗口。

在 Windows 上

Windows 是一个特例:Linux 和 MacOS 预装了 Bash,而 Windows 没有。它自带两个内置 Shell:cmdPowershell。不过,本教程的其余部分及其后续章节假设您运行的是 Bash。原因是 Bashbash几乎无处不在,无论是在个人工作站还是服务器上。除此之外,Bash 还附带了大量工具和命令,我们将在下一章详细介绍。

幸运的是,Windows 10 自 2019 年起可以通过Windows Subsystem for Linux (WSL) 原生运行 bash。我们建议您按照本教程中的说明进行操作

现在可以在 Windows 上运行 bash
现在可以在 Windows 上运行 bash

运行我们的第一个命令

打开终端后,首先看到的是提示符。每次 Shell 准备好执行下一个命令时,都会显示提示符
。提示符通常
会显示对用户有用的信息。在我的例子中,br是我的
用户名,morenika是我的计算机名称(它的主机名)。

`br@morenika:~$` 是我的提示符
br@morenika:~$是我的提示

黑色矩形称为光标。它代表您当前的
打字位置。

您的提示符的实际外观取决于您的操作系统和 Shell。如果您的提示符与以下示例中的提示符不完全相同,请不要担心。

我们将运行的第一个命令是ls(代表list
directory
)。默认情况下,该命令会列出
当前所在目录中的所有目录和文件。要运行该
命令,我们需要ls在提示符后输入,然后点击
Enter

在我们的命令之后和下一个提示之前显示的文本
是命令的输出

br@morenika:~$ ls
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos


这些就是我的个人目录(也称为主目录下的所有文件和目录。
为了确保万无一失,我们打开图形化文件资源管理器检查一下。

正如预期的那样,我们没有被骗
正如预期的那样,我们没有被骗

shell 对大小写敏感:小写命令
与大写命令不同。

br@morenika:~$ LS
bash: LS: command not found

从现在起,我们将忽略br@morenika:~$提示前缀,而
只使用$, 来使我们的示例保持简短。

命令参数

在上一个示例中,我们列出了我的
主目录中的所有文件和目录。如果我想列出bin
输出中可见的目录中的所有文件怎么办?在这种情况下,我可以将其
bin作为参数传递给ls命令。

$ ls bin
bat            fix-vlc-size  lf          terraform  vpnconnect
clean-desktop  itresize      nightlight  tv-mode

通过bin向命令传递参数ls,我们告诉它要
查找的位置,从而改变了它的行为。请注意,可以
向一个命令传递多个参数。

$ ls Android bin
Android:
Sdk

bin:
bat  clean-desktop  fix-vlc-size  itresize  lf  nightlight  terraform  tv-mode  vpnconnect

在该示例中,我们向ls:bin和传递了两个参数Android
ls然后继续列出这两个目录各自的内容。

想想看,在文件资源管理器的图形用户界面 (GUI) 中,你会如何操作。你
可能会进入第一个目录,然后返回到
父目录,最后进入下一个目录。
终端可以让你更高效。

命令选项

现在,假设我还想查看位于 下的文件bin
有多大。没问题!该ls命令有一些选项可以用来调整其
行为。该-s选项会ls显示每个文件的大小(以
千字节为单位)。

$ ls -s bin
total 52336
 4772 bat                4 itresize    44296 terraform
    4 clean-desktop   3244 lf              4 tv-mode
    4 fix-vlc-size       4 nightlight      4 vpnconnect

虽然这很好,但我更喜欢以人性化的
方式显示文件大小。我可以添加-h选项来进一步指定ls需要执行的操作。

$ ls -s -h bin
total 52M
4.7M bat            4.0K itresize     44M terraform
4.0K clean-desktop  3.2M lf          4.0K tv-mode
4.0K fix-vlc-size   4.0K nightlight  4.0K vpnconnect

我可以用空格分隔两个选项,也可以将它们分组为一个
选项。

$ ls -sh bin
total 52M
4.7M bat            4.0K itresize     44M terraform
4.0K clean-desktop  3.2M lf          4.0K tv-mode
4.0K fix-vlc-size   4.0K nightlight  4.0K vpnconnect

我最终希望每个文件及其相关大小都显示在
单独的一行上。输入这个-1选项!

 $ ls -s -h -1 bin
total 52M
4.7M bat
4.0K clean-desktop
4.0K fix-vlc-size
4.0K itresize
3.2M lf
4.0K nightlight
 44M terraform
4.0K tv-mode
4.0K vpnconnect

简短的选项可以让你快速输入命令,但
输入一定数量的选项后,结果可能难以理解,你可能
会开始怀疑命令到底在做什么。
幸运的是,选项可以有长格式短格式。例如,
-s可以用它的长格式 代替--size,也-h可以用 代替
--human-readable

$ ls --size --human-readable -1 bin
total 52M
4.7M bat
4.0K clean-desktop
4.0K fix-vlc-size
4.0K itresize
3.2M lf
4.0K nightlight
 44M terraform
4.0K tv-mode
4.0K vpnconnect

这样一来,命令就更容易理解了!你会注意到,
我们仍然使用了选项的缩写形式-1。原因是
这个选项根本没有完整形式。

总结

  • 终端是一个应用程序,通过它可以与 shell 进行交互
  • 您可以通过在 shell 的命令行中输入命令并点击来执行命令Enter
  • 一个命令可以接受 0 个、1 个或多个参数
  • 可以通过传递选项来改变命令的行为
  • 按照惯例,期权可以有多种形式:短期期权和/或长期期权。

以下是命令不同部分的摘要
以下是命令不同部分的摘要

管理文件

到目前为止,我们已经了解了如何运行命令、通过
传递命令行参数和选项来更改其行为,以及ls如何
列出目录的内容。现在是时候学习如何
管理文件了,例如创建文件和目录、复制和
移动它们、创建链接等等。本节的目标是教你如何 在终端中
完成所有通常在文件资源管理器中执行的操作。

pwd, cd:在目录之间导航

到目前为止,我们运行的每个命令都是从主目录(存放所有文档、下载内容等的目录)执行的。就像 在图形文件编辑器中导航目录
一样,您 也可以在终端中执行此操作。

在开始任何操作之前,我们首先需要知道当前位置。输入
pwd,代表print working directory。此命令会显示
你当前的工作目录(也就是你当前所在的位置)。

$ pwd
/home/br

现在我们找到了方向,终于可以四处走动了。我们
可以用cd命令来做到这一点,它代表(你可能已经猜到了
更改目录

$ cd Documents
$ pwd
/home/br/Documents
$ cd ./invoices
$ pwd
/home/br/Documents/invoices
$ cd 2020
$ pwd
/home/br/Documents/invoices/2020

由于2020为空,我们无法继续前进。但是,我们也可以使用
返回父目录
(包含我们 当前所在目录的目录) cd ..

$ pwd
/home/br/Documents/invoices/2020
$ cd ..
$ pwd
/home/br/Documents/invoices

我们不必每次都逐级切换目录。我们可以
一次切换到多个目录。

$ pwd
/home/br/Documents/invoices
$ cd ../..
$ pwd
/home/br

我们还可以同时进入多个目录

$ pwd
/home/br
$ cd Documents/invoices/2020

不带参数运行cd会将您带回到主目录。

$ pwd
/home/br/Documents/invoices/2020
$ cd
$ pwd
/home/br

跑步cd -会将您带回到之前的位置。

$ pwd
/home/br/Documents/invoices/2020
$ cd /home/br
$ cd -
$ pwd
/home/br/Documents/invoices/2020

你可能会疑惑,为什么cd ..要返回到父目录?
这是什么..意思?为了理解这一点,我们需要探索路径
的工作原理。

路径:根路径、绝对路径和相对路径

如果您以前从未使用过终端,并且只使用
图形文件浏览器在目录之间导航,那么
路径的概念可能有点陌生。路径是
文件系统中文件或文件夹的唯一位置。最简单的解释方法是
描述文件和目录在磁盘上的组织方式。

基本目录(也称为
目录
,简称/)是层次结构中的最高目录
:它包含系统中的每个其他文件和目录
,每个目录可能包含其他目录,从而形成一个
看起来像树的结构。

您的磁盘组织得像一棵树
您的磁盘组织得像一棵树

让我们看看根目录包含什么/

$ ls /
bin  boot  dev  etc  home  lib  lib64  lost+found  media
mnt opt  proc  root  run  sbin  srv  sys  tmp  usr  var

好的,这里面有几件事。我们
之前讨论过主目录,记得吗?事实上,所有用户的主
目录都位于home目录下。由于home位于
/,我们可以通过它的绝对路径来引用它,也就是说,
从根目录开始到给定目录的完整路径。对于
home,它的绝对路径是/home,因为它直接位于 下
/

任何以 开头的路径/都是绝对路径。

然后我们可以使用该路径通过命令检查home目录的内容
ls

$ ls /home
br

的绝对路径br是。每个目录 与其父目录之间用/home/br分隔。这就是根目录被称为的原因 它是唯一没有父目录的目录。
//

任何不以 开头的路径/都是相对路径,这意味着它是相对于
当前目录的。当我们执行ls bin命令时,实际上bin
相对路径。事实上,我们在
中执行了该命令/home/br,这意味着 的绝对路径bin
/home/br/bin

磁盘上的每个文件夹都有一个指向其自身的链接,称为.,以及一个指向
其父文件夹的链接,称为..

`.` 链接指向文件夹本身,`..` 链接指向<br>文件夹的父级
链接.指向文件夹本身,..链接指向文件夹的父文件夹

我们可以使用这些...链接来构建相对路径。
例如,如果您当前位于/home/br,则可以将该文件夹称为
Android意思./Android是“ 位于(当前目录)下的Android文件夹”。
.

$ ls ./Android
Sdk

如果您位于 下/home/br/Android,您也可以将其
/home/br/Downloads称为../Downloads

按照“Android”的“..”链接将带您回到“home”目录
以下Android链接..将带您回到home导演

ls -a允许您查看隐藏文件,即所有以
点开头的文件。我们确实可以看到...链接!

$ ls -a
.  ..  Sdk

mkdir:创建目录


为了确保在测试本章中的命令时不会弄乱您的个人文件,我们将首先创建一个
名为的新目录进行实验experiments

你可以使用make directory 命令mkdir创建一个新目录。执行该命令后 你将在当前目录中创建该目录。 我们来测试一下。
mkdir experiments
experiments

$ ls
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos

$ mkdir experiments
$

请注意,该mkdir命令没有显示任何内容。
乍一看可能感觉有点奇怪,但这就是这些命令的理念:只有
出现问题时才显示一些内容。换句话说,好消息就没消息了

我们现在可以检查目录是否已创建。

$ ls
Android          bin   Desktop  Downloads  experiments      Music     Videos
AndroidStudioProjects  code  Documents  Dropbox    Firefox_wallpaper.png  Pictures

我们还可以通过打开文件资源管理器来查看该目录。

我们刚刚在终端中创建的目录可以在文件资源管理器中看到。终端以文本形式显示信息,而文件资源管理器以图形形式显示信息。
我们刚刚在终端中创建的目录可以在文件资源管理器中看到。终端以文本形式显示信息,而文件资源管理器以图形形式显示信息。

运行mkdir预先存在的命令会导致其失败并显示
错误消息。

$ mkdir experiments
mkdir: experiments: File exists

如果我们想在 中创建一个experiments名为 的目录art
而另一个名为 的目录paintings位于 中,该怎么办art

$ mkdir experiments/art/paintings
mkdir: experiments/art: No such file or directory

这里显然出了点问题。mkdir它抱怨无法在目录内
创建,因为它不存在。我们 可以在两个单独的命令中创建,然后创建,但 幸运的是,它提供了一个选项, 即使目录已经存在,该选项也会成功创建每个 父目录。paintingsexperiments/art
artpaintings
mkdir-pmkdir


-p, --parents: no error if existing, make parent directories as needed

看起来这正是我们所需要的!让我们看看它是否
按预期工作。

$ mkdir -p experiments/art/paintings
$ ls experiments
art
$ ls experiments/art
paintings
$ ls experiments/art/paintings
$

cp, mv:移动文件

cp(代表copy)允许您将文件或目录复制到
另一个位置。

$ cp Documents/readme experiments/art
$ ls experiments/art
paintings   readme
$ ls Documents
readme

您还可以使用 将文件从一个位置移动到另一个位置mv

$ mv experiments/art/readme experiments
$ ls experiments
art   readme
$ ls experiments/art
paintings

但这似乎对目录不起作用。

$ cp experiments/art experiments/art-copy
cp: experiments/art is a directory (not copied).

默认情况下,cp仅适用于文件,不适用于目录。我们需要
使用-r选项来指示cp递归复制experiments/art
experiments/art-copy,这意味着cp将复制目录及其
包含的每个文件和目录。

$ cp -r experiments/art experiments/art-copy
$ ls experiments
art-copy art  readme
$ ls experiments/art
paintings
$ ls experiments/art-copy
paintings

最后,您可以使用mv来重命名文件或目录。
听起来可能有点奇怪,没有rnrename命令,但
重命名文件实际上只是将其移动到
同一目录中的另一个位置。

$ mv experiments/readme experiments/README
$ ls experiments
README    art-copy art

rm:删除文件和目录

rm副本允许您删除文件和目录。

请小心rm,当文件被删除时,它不会被移到垃圾箱
,而是会消失。

$ rm experiments/README
$ ls experiments
art-copy art

rm行为类似于:它只允许您 使用该选项cp删除目录
-r

$ rm experiments/art
rm: experiments/art: is a directory
$ rm -r experiments/art
$ ls experiments
art-copy
$ rm -r experiments/art-copy
$ ls experiments
$

ln:创建链接

你有没有在桌面上创建过某个文件的快捷方式?
这在后台是通过符号链接实现的。链接指向
原始文件,允许你从多个位置访问该文件,
而无需在磁盘上实际存储多个副本。

我们可以使用ln -s命令(-s代表
符号)创建这样的链接。

$ pwd
/home/br
$ ln -s Documents/readme Desktop/my-readme

使用-l选项ls,我们可以看到链接指向哪里。

$ ls -l Desktop
total 0
lrwxr-xr-x  1 br  br  21 Jan 17 16:48 my-readme -> /home/br/Documents/readme

我个人记住参数顺序的方法是
记住s 代表源:源文件位于-s选项之后。
ln -s <source>

tree:可视化文件和子文件夹

tree
以树状结构显示当前目录(或参数目录)及其子文件夹的内容。
快速浏览目录的当前内容非常有用。

$ tree experiments
experiments
|__ art
    |__ paintings

2 directories, 0 files

tree默认情况下可能不会安装,具体取决于您的系统。我们
在此提及它,因为我们将在后续章节中重复使用它。

学习新的选择

获取帮助

如果你不知道如何记住所有这些选项,
别担心。没人指望你能记住所有命令的所有选项
。你可以参考命令文档,而
不必全部记住。

大多数命令都带有一个-h(或--help) 选项,该选项
将显示命令本身可以采用的选项列表以及
它们的作用。

$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.

Mandatory arguments to long options are mandatory for short options too.
  -a, --all                  do not ignore entries starting with .
  -A, --almost-all           do not list implied . and ..
      --author               with -l, print the author of each file
  -b, --escape               print C-style escapes for nongraphic characters
      --block-size=SIZE      with -l, scale sizes by SIZE when printing them;
                               e.g., '--block-size=M'; see SIZE format below
  -B, --ignore-backups       do not list implied entries ending with ~
  -c                         with -lt: sort by, and show, ctime (time of last
                               modification of file status information);
                               with -l: show ctime and sort by name;
                               otherwise: sort by ctime, newest first
[cut for brevity]

值得注意的是,有些选项同时接受短格式和长
格式,例如-a/--all,而有些选项只接受短格式
( -c) 或长格式 ( --author)。这并没有真正的规则,只是
惯例。有些命令甚至可能不接受--help选项,但大多数(
如果不是全部)常用命令都会接受选项。

注意-h并不总是 的缩写--help。事实上,我们已经看到
打印ls --help了所有可用命令的概述,而 则以
ls -h人类可读的格式显示单位!

阅读手册

有时,没有--help可用的选项,或者输出不够
清晰或冗长,不符合你的口味,或者输出太长,
难以浏览。阅读命令 页面(man代表手册)通常是一个好主意。man

让我们尝试一下,输入以下命令。

$ man ls

`man ls` 显示 `ls` 命令的手册:您需要了解的有关 `ls` 用途的所有信息。
man ls显示命令手册ls:您需要了解的有关其ls用途的所有信息。

阅读概要

man为您提供了一个概要,描述了每行命令的具体用法
以及相关的选项和参数。

概要ls如下

SYNOPSIS
       ls [OPTION]... [FILE]...

[OPTION]and[FILE]表示选项和文件都是
可选的。正如我们在本章开头所见,单独运行
ls它就会打印当前工作目录的内容。

下面...[OPTION][FILE]表示
可以将几个选项和几个文件参数作为参数传递给ls
如下例所示。

$ ls -sh Android bin
Android:
total 4.0K
4.0K Sdk

bin:
total 52M
4.7M bat            4.0K fix-vlc-size  3.2M lf           44M terraform  4.0K vpnconnect
4.0K clean-desktop  4.0K itresize      4.0K nightlight  4.0K tv-mode

如果我们看一下mkdir概要,我们会发现选项是可选
的,但我们必须为其提供一个或多个要创建的目录,
因为DIRECTORY它不在方括号之间。

SYNOPSIS
       mkdir [OPTION]... DIRECTORY...

DESCRIPTION部分将列出所有可能的选项(短形式和长
形式)及其效果。

浏览手册

当你运行 时man,命令手册将显示在
分页器中,分页器是一个
帮助用户逐页获取输出的软件。最常用的
分页器命令之一是(顺便说一下,它是less功能更丰富的继承者,因为少即是多)。第一次使用分页器 可能会感到困惑,因为你可能不知道如何 导航。
more

您可以输入的最有用的命令less是:

  • h:显示less帮助
  • q: 出口less
  • /pattern:查找位于光标当前位置之后的输入文本
  • n:转到下一个模式发生处
  • ?pattern:查找位于光标当前位置之前的输入文本
  • N转到模式的上一次出现
  • 向上或向下箭头可向上或向下导航一行
  • PageUp 和 PageDown 键用于向上或向下导航页面
  • g转到文件开头
  • G转到文件末尾

例如,如果您不确定某个-s ls选项的作用,您
可以在 中键入man ls,然后键入。键入直到 找到 的文档(或者,如果您输入太多,可以返回 )。完成后,您可以键入退出/-slessn
-s, --sizeN
lessq

虽然它底层man用来帮助你阅读文档, 但你也可以用它来翻阅磁盘上的任何文件。例如 ,我可以在我的电脑上使用此命令。less
less

$ less Documents/readme

您可以通过在阅读手册页时less键入、在终端中 键入,甚至键入来查看帮助本身h
less --helpman less

就像 一样lsman它本身就是一个命令,并且和大多数
命令一样,它有手册!你可以 输入以下命令来了解更多关于man它的信息:

$ man man

低调,手册的手册。
低调,手册的手册。

命令输入/输出流

在我们全面解释是什么让 Shell 如此强大之前,我们需要先
解释一下什么是输入输出(Input Output
Stream )。每次运行命令时,Shell 都会执行一个
进程 (Process),该进程负责运行命令,并将
其输出传回终端。输入/输出流是
Shell 将输入发送到进程并从
进程调度输出的方式。

每个进程默认有3个流:

  • stdin(或标准输入):为命令提供输入
  • stdout(或标准输出):显示命令的输出
  • stderr(或标准错误):显示命令的错误

每个流都有一个关联的文件描述符,即 shell 用来
引用该流的数字。stdin例如,有文件描述符 0,stdout
1,stderr有 2。

stdin(文件描述符 0)是进程输入流,stdout(文件描述符 1)是进程输出流,stderr(文件描述符 2)是进程错误流
stdin(文件描述符 0)是进程输入流,stdout(文件描述符 1)是进程输出流,stderr(文件描述符 2)是进程错误流。

将输出重定向到文件


将命令的输出“保存”到文件,以便稍后进一步处理或发送给其他人,非常方便。您
可以使用运算符将命令的>重定向到 文件。stdout

$ ls /home/br > ls-home.txt

ls-home.txt然后我们可以使用该命令显示文件的内容
cat

$ cat ls-home.txt
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin                    Documents  Firefox_wallpaper.png  Videos

如果文件不存在,shell 会在重定向时创建它
。如果文件在
重定向时存在,则会被覆盖,这意味着该
文件之前包含的所有内容都将被重定向命令的输出所替换

在该示例中,我们使用echo命令,该命令只是将
参数文本发送到其stdout

$ cat ls-home.txt
Android                code       Downloads              Music
AndroidStudioProjects  Desktop    Dropbox                Pictures
bin
$ echo "Hello world!" > ls-home.txt
$ cat ls-home.txt
Hello world!

如果要将命令的输出附加到文件而不
覆盖其内容,则可以使用>>运算符代替>

$ cat echoes
cat: echoes: No such file or directory
$ echo "Hey, I just met you, and this is crazy" >> echoes
$ echo "so here's my echo, so cat it maybe" >> echoes
$ cat echoes
Hey, I just met you, and this is crazy
so here's my echo, so cat it maybe

将文件重定向到命令的输入

就像您可以将命令重定向stdout到文件一样,您也可以
将文件重定向到命令sdtin

在该示例中,我们将文件的内容重定向echoes到命令
的输入,计算其输入 流或通过参数传递的文件wc -l的行数。

$ cat echoes
Hey, I just met you, and this is crazy
so here's my echo, so cat it maybe
$ wc -l < echoes
2

当然,你也可以在一个命令中组合使用<,>和运算符 。在下面的示例中,我们将文件的内容重定向到命令,并将该 命令的输出重定向到文件。>>

echoeswc -l
echoes-lines

$ wc -l < echoes > echoes-lines
$ wc -l < echoes > echoes-lines
$ cat echoes-lines
2
$ cat echoes
Hey, I just met you, and this is crazy
so here's my echo, so cat it maybe

将多行重定向到命令的输入


可能会遇到需要 向命令传递多行输入的情况,而该<运算符在这种情况下会失败
,因为它只处理文件。幸运的是,你的 Shell 提供了
heredoc (此处文档)运算符来实现这一点。<<

heredoc 重定向具有以下语法:

command << DELIMITER
a multi-line
string
DELIMITER

可以DELIMITER是您选择的任何字符串,尽管EOF(“
文件结束”)非常常用。

让我们考虑以下示例:

$ cat <<EOF
My username is br
I'm living at /home/br
EOF

该命令将输出以下文本块:

My username is br
I'm living at /home/br

<<您可以通过组合和运算符将该块重定向到文件中
>

$ cat > aboutme <<EOF
My username is br
I'm living at /home/br
EOF
$ cat aboutme
My username is br
I'm living at /home/br

重定向stderr

让我们考虑下面的例子。

$ cat -n notthere > notthere-with-line-numbers
cat: notthere: No such file or directory
$ cat notthere-with-line-numbers

为什么notthere-with-line-numbers即使我们将命令的输出
重定向cat -n notthere到该文件,它仍然是空的?原因
是,我们实际上并没有将命令的输出重定向到该文件,而是
重定向了命令本身stdout。由于该文件notthere
存在,cat命令失败,并在其
stderr流(未被重定向)上显示一条错误消息。

您可以使用文件描述符来重定向进程流。
还记得吗? 0 表示stdin, 1 表示stdout, 2 表示stderr

$ cat -n notthere  2>errors.txt
$ cat errors.txt
cat: notthere: No such file or directory

stderr下图可以说明此重定向。

`cat` 显示的任何错误都将被重定向到 `errors.txt` 文件中
显示的任何错误cat都将被重定向到errors.txt文件中

您还可以将命令重定向sdterr到一个文件,并将其stderr
重定向到另一个文件。

$ cat -n notthere >output.txt 2>errors.txt
$ cat output.txt
$ cat errors.txt
cat: notthere: No such file or directory

正常输出将被重定向到“output.txt”,而错误将被重定向到“errors.txt”
正常输出将被重定向到,output.txt而错误将被重定向到errors.txt

也可以将命令重定向stderr到其stdout
使用中2>&1。这将有效地将两个流合并为一个

$ cat notthere > output.txt 2>&1
$ cat output.txt
cat: notthere: No such file or directory

`cat` 的 stdout 和 stderr 合并成一个流
cat的 stdout 和 stderr 合并成一个流

重定向的顺序总让我感觉有点奇怪。
你可能会觉得下面的语法应该能正常工作,因为它(至少对我来说)
更符合逻辑,即“将所有错误重定向到 stdout,并将
所有内容重定向到一个文件”。然而,它却不起作用。

$ cat notthere 2>&1 > output.txt
cat: notthere: No such file or directory
$ cat output.txt
$

编写命令

能够使用大量各有用途的命令
固然强大。然而,shell 的真正强大之处在于
这些命令可以组合使用。这正是终端
与图形应用程序理念截然不同的地方。GUI允许您使用一组预定义的工具,
Shell 允许您将命令组合成您自己 的专用工具。

这是通过管道:完成的|
允许将一个命令的输出流重定向到另一个
命令的输入流。

$ command1 | command2

管道的工作原理很简单,就是将上stdout一个命令的流连接到下一个命令的
stdin。简而言之,上一个
命令的输出将成为下一个命令的输入。

`ls` 通过将 `wc` 的输出重定向到 `wc` 的输入,*管道* 将其传入 `wc`。管道允许将命令组合并组装成管道,这使得终端非常强大。
ls通过将其输出重定向到 的输入,将其通过管道传输。管道允许将命令组合并组装到管道中,这使得终端非常强大。wcwc

当然,您可以链接尽可能多的命令并创建命令
管道。

$ command1 | command2 | command3 | ... | commandN

当您执行时command1 | command2,您的 shell 会 同时启动所有命令,并且 命令运行时,命令的输出会流入下一个命令。

例如,假设我想统计文件
Downloads夹中的文件数量。为此,我可以结合使用lswc(用于
字数统计)命令。wc与选项一起使用时-l,可以
统计输入的行数。

$ ls -1 ~/Downloads | wc -l
34

现在,假设我只想统计
Downloads文件夹中 pdf 文件的数量,而不是全部。没问题,grep
帮你!grep允许根据给定的模式过滤输入(
grep下一章会详细介绍)。通过使用,我们将grep pdf输出过滤为仅包含“pdf”的文件名,然后计算 使用 过滤的文件名数量
ls -1
wc -l

$ ls -1 ~/Downloads | grep pdf | wc -l
22

更进一步:将输出重定向到控制台和文件

tee命令允许你将命令写入stdout文件
,同时仍将其显示在控制台中。如果
你想将命令的输出存储在文件中,但仍能实时
查看其执行情况,这将非常有用。

$ ls -1 | head -n 2 | tee output.txt
Android
code
$ cat output.txt
Android
code

“tee” 因管道中使用的 T 型分离器而得名。
tee以管道中使用的 T 型分离器命名。

逃离困境

命令输入错误,缺少参数

如果您输入了错误的命令,或者忘记添加参数,您
的 shell 可能会挂起,无法执行任何操作。例如
,输入以下任意命令。

$ cat
$ echo 'hello world

第一个命令挂起是因为它正在等待stdin
流中的输入,因为没有提供参数 file。第二个
命令则是因为缺少匹配的单引号。在这两种情况下,你都
可以通过点击Ctrl-来摆脱这种情况C
,它会向命令发送一个中断信号,从而终止该命令。

注意:如果您的 shell 卡在接收输入时(如cat示例中所示),您也可以通过点击-
来干净地退出它 ,这将发送一个特殊的 EOF(“文件结束”)字符,向 命令指示其输入现已关闭。CtrlD


$ cat
hello
hello
world
world
# Ctrl-D
$

转义字符

想象一下,磁盘上有一个名为的文件my file,并且
您想使用 显示其内容cat

$ cat my file
cat: my: No such file or directory
cat: file: No such file or directory

在上面的例子中,cat命令被赋予了两个参数my
file,但它们都不对应任何现有文件。我们有两个
解决方案来解决这个问题:用引号括住文件名,或者使用转义字符

$ cat 'my file'
That file has spaces in it...
$ cat "my file"
That file has spaces in it...

通过在文件名两边加上引号,你就是在告诉你的 shell,
引号之间的内容都是一个参数。

如前所述,我们还可以使用反斜杠转义
字符,它表示后面的任何字符都没有
任何特殊含义。

$ cat my\ file
That file has spaces in it...

通过使用\(反斜杠字符后跟空格),我们向
shell 表明该空格仅仅是一个空格,而不应被
解释为两个参数之间的分隔符。

概括

在那一章中,我们发现了什么是终端:一个应用程序,您可以在其中键入文本命令,然后由 称为 shell 的
程序执行这些命令。

一开始面对终端可能会让人感到畏惧,因为你可能不
知道该输入什么命令。
然而,学习如何使用终端是成为软件工程师旅程的一部分。就像任何其他强大的工具一样,它可能很难学习,但 一旦你习惯了它,
你的工作效率也会大大提高。

在终端中工作的基本理念是,通过使用管道和流重定向,可以自由地
组合不同的工具,而这或许是
工具开发者最初未曾预见到的
。与其使用单一工具来
执行有限的任务,不如自由地组合一堆
互不相关的命令,并通过连接它们的输入和
输出流来实现协同工作。

下一章中,我们将深入研究文本处理命令,这些命令
通过管道链接在一起时会非常强大。

更进一步

1.1:查看ls手册并研究该-a选项的
作用。运行。和目录ls -a ~/是什么 以 开头的文件是什么...
.

1.2:运行命令并将其输出重定向到文件中,但
在终端中显示任何错误。

1.3:运行命令并将其输出重定向到文件中,并将任何
错误重定向到其他文件中。

1.4:运行一个命令并将其输出和错误重定向到
同一个文件中,同时将它们全部显示在屏幕上。

1.5:使用 heredoc 重定向创建一个包含文本的新文件。

1.6:给定一个文件,之间echoes有什么区别
wc -l echoescat echoes | wc -lwc -l < echoes


《面向有抱负的软件开发人员的基本工具和实践》是由 Balthazar Rouberol 和Etienne Brodu共同发起的自费出版图书项目,他们曾是室友、朋友和同事,旨在赋能新一代的开发人员。我们目前正在努力创作!

本书将帮助您搭建高效的开发环境,并熟悉相关工具和实践,这些工具和实践将与您选择的编程语言一起,极大地帮助您成长为一名软件开发者。本书涵盖的主题包括:掌握终端操作、在 Shell 中进行配置和提高效率、使用 进行代码版本控制的基础知识、SQL 基础知识、诸如和正则表达式git之类的工具、网络基础知识,以及软件工程和协作的最佳实践。Makejq

如果您对该项目感兴趣,我们邀请您加入邮件列表

鏂囩珷鏉ユ簮锛�https://dev.to/brouberol/discovering-the-terminal-5ddf
PREV
运行您自己的博客的最佳 AI 工具
NEXT
成为高级开发人员的 6 个技巧