发现终端
发现终端
最初发表在我的博客上。
目录
发现终端
当人们想象程序员时,他们通常会想象
一个人坐在电脑屏幕前,屏幕上
飞快地显示着难以辨认的文本流,就像《黑客帝国》里那样。让我们来澄清
一下。这并非事实,至少在大多数情况下并非如此。
然而,《黑客帝国》也有一些地方是对的。程序员的工作是代码,
顾名思义,必须先学习才能理解
。任何不熟悉读写代码的人
只会看到乱码。这些电影通常也
对程序员在终端中输入命令这一事实做出了正确的描述。
什么是终端?
人们日常使用的大多数应用程序都具有图形用户界面 (GUI)。想想 Photoshop、
Firefox 或您的智能手机应用程序。这些应用程序功能强大,但用户通常 首先
受限于其中实现的功能。如果您突然想使用 Photoshop 中某个新功能,而该功能尚未提供,该怎么办?您可能最终 要么等待最新版本发布,要么不得不 安装另一个应用程序。
然而,程序员工具箱中最重要的工具之一却属于
另一种类型。它被称为终端,它是一个命令行应用程序。也就是说,你
输入一个命令,你的计算机就会执行该命令,并
在终端中显示输出。
换句话说,这是一款你可以向计算机发出
指令的应用程序。如果你知道如何发出指令,你的计算机会很乐意服从。
但是,如果你命令它做一些愚蠢的事情,它也会服从。
— 你:“计算机,创建该文件夹。”
— 计算机:“当然。”
— 您:“现在将桌面上的所有文件放入该新文件夹中。”
— 计算机:“没问题。”
— 你:“现在永久删除该文件夹以及里面的所有内容。”
— 计算机:“完成。”
— 你:“等等,不,我的错误,我要把它拿回来。”
— 计算机:“抱歉,正如您所要求的,它已经全部消失了。”
- 你: ”…”
— 计算机:“我一点也不抱歉。”
这句名言再正确不过了:
能力越大,责任越大
学习使用终端确实会彻底改变你与计算机的交互方式。 终端
不再局限于应用程序,而是让你可以自由无限制地 访问计算机的各个部分。你不再受制于有限的命令数量,而是 会受到已知命令数量的限制。因此, 学习如何使用终端将帮助你深入了解 计算机的工作原理。让我们看看能做些什么。我们从小处着手,但相信 我,它会越来越好。
你的第一步
首先,让我们定义几个词。
终端是一个可以在计算机上打开的应用程序,
您可以在其中通过命令行界面 (CLI) 输入命令。当
您按下Enter键盘上的某个键时,shell 会执行该命令
,并将结果显示在终端中。
在计算机发展的早期,视频终端是实际的物理设备,用于在可能占据 整个房间的
远程计算机上执行命令。
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:cmd
和Powershell
。不过,本教程的其余部分及其后续章节假设您运行的是 Bash。原因是 Bashbash
几乎无处不在,无论是在个人工作站还是服务器上。除此之外,Bash 还附带了大量工具和命令,我们将在下一章详细介绍。
幸运的是,Windows 10 自 2019 年起可以通过Windows Subsystem for Linux (WSL) 原生运行 bash。我们建议您按照本教程中的说明进行操作。
运行我们的第一个命令
打开终端后,首先看到的是提示符。每次 Shell 准备好执行下一个命令时,都会显示提示符
。提示符通常
会显示对用户有用的信息。在我的例子中,br
是我的
用户名,morenika
是我的计算机名称(它的主机名)。
黑色矩形称为光标。它代表您当前的
打字位置。
我们将运行的第一个命令是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
。
磁盘上的每个文件夹都有一个指向其自身的链接,称为.
,以及一个指向
其父文件夹的链接,称为..
。
我们可以使用这些.
和..
链接来构建相对路径。
例如,如果您当前位于/home/br
,则可以将该文件夹称为
,Android
意思./Android
是“ 位于(当前目录)下的Android
文件夹”。.
$ ls ./Android
Sdk
如果您位于 下/home/br/Android
,您也可以将其/home/br/Downloads
称为../Downloads
。
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
它抱怨无法在目录内
创建,因为它不存在。我们 可以在两个单独的命令中创建,然后创建,但 幸运的是,它提供了一个选项, 即使目录已经存在,该选项也会成功创建每个 父目录。paintings
experiments/art
art
paintings
mkdir
-p
mkdir
-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
来重命名文件或目录。
听起来可能有点奇怪,没有rn
或rename
命令,但
重命名文件实际上只是将其移动到
同一目录中的另一个位置。
$ 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
如下
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
,然后键入。键入直到 找到 的文档(或者,如果您输入太多,可以返回 )。完成后,您可以键入退出。/-s
less
n
-s, --size
N
less
q
虽然它底层man
用来帮助你阅读文档, 但你也可以用它来翻阅磁盘上的任何文件。例如 ,我可以在我的电脑上使用此命令。less
less
$ less Documents/readme
您可以通过在阅读手册页时less
键入、在终端中 键入,甚至键入来查看帮助本身!h
less --help
man less
就像 一样ls
,man
它本身就是一个命令,并且和大多数
命令一样,它有手册!你可以 输入以下命令来了解更多关于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)是进程错误流。
将输出重定向到文件
将命令的输出“保存”到文件,以便稍后进一步处理或发送给其他人,非常方便。您
可以使用运算符将命令的>
重定向到 文件。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
当然,你也可以在一个命令中组合使用<
,>
和运算符 。在下面的示例中,我们将文件的内容重定向到命令,并将该 命令的输出重定向到文件。>>
echoes
wc -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
文件中
您还可以将命令重定向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
也可以将命令重定向stderr
到其stdout
使用中2>&1
。这将有效地将两个流合并为一个
。
$ cat notthere > output.txt 2>&1
$ cat output.txt
cat: notthere: No such file or directory
重定向的顺序总让我感觉有点奇怪。
你可能会觉得下面的语法应该能正常工作,因为它(至少对我来说)
更符合逻辑,即“将所有错误重定向到 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
当然,您可以链接尽可能多的命令并创建命令
管道。
$ command1 | command2 | command3 | ... | commandN
当您执行时command1 | command2
,您的 shell 会 同时启动所有命令,并且 命令运行时,命令的输出会流入下一个命令。
例如,假设我想统计文件Downloads
夹中的文件数量。为此,我可以结合使用ls
和wc
(用于
字数统计)命令。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
逃离困境
命令输入错误,缺少参数
如果您输入了错误的命令,或者忘记添加参数,您
的 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 echoes
cat echoes | wc -l
wc -l < echoes
《面向有抱负的软件开发人员的基本工具和实践》是由 Balthazar Rouberol 和Etienne Brodu共同发起的自费出版图书项目,他们曾是室友、朋友和同事,旨在赋能新一代的开发人员。我们目前正在努力创作!
本书将帮助您搭建高效的开发环境,并熟悉相关工具和实践,这些工具和实践将与您选择的编程语言一起,极大地帮助您成长为一名软件开发者。本书涵盖的主题包括:掌握终端操作、在 Shell 中进行配置和提高效率、使用 进行代码版本控制的基础知识、SQL 基础知识、诸如和正则表达式git
之类的工具、网络基础知识,以及软件工程和协作的最佳实践。Make
jq
如果您对该项目感兴趣,我们邀请您加入邮件列表!
鏂囩珷鏉ユ簮锛�https://dev.to/brouberol/discovering-the-terminal-5ddf