原文:https://datascienceatthecommandline.com/2e/chapter-2-getting-started.html
贡献者:Ting-xin
在这一章中,我需要确定你能够利用命令行做数据科学,为此你需要能满足一些条件。条件主要分为三个部分:(1)拥有与我在本书中使用的相同的数据集,(2)拥有一个适当的环境,拥有我在本书中使用的所有命令行工具,(3)了解使用命令行时的基本概念。
首先,我描述了如何下载数据集。其次,我解释了如何安装 Docker 镜像,它是一个基于 Ubuntu Linux 的虚拟环境,包含所有必要的命令行工具。随后,我通过例子介绍了基本的 Unix 概念。
在本章结束时,你将掌握进行数据科学的第一步,也就是获取数据。
数据集下载步骤:
dsatcl2e-data
,然后记住这个目录在哪里接下来我将介绍如何安装包含处理这些数据的环境,它包含的所有必要的命令行工具。
在本书中,我们使用了许多不同的命令行工具。Unix 通常预装了许多命令行工具,并提供了许多包含相关工具的包。自己独立安装这些包通常不会太难。然而,我们也会使用那些不能以包的形式提供的工具,这也需要更多涉及安装的手动操作。为了获得必要的命令行工具而不必经历每个工具的安装过程,我建议安装专门为本书创建的 Docker 镜像,无论你的操作系统是 Windows、macOS 还是 Linux 。
Docker 镜像是一个或多个应用及其所有依赖项的包。Docker 容器是一个运行镜像的隔离环境,你可以使用docker
命令行工具(这也是你下面要做的)或 Docker GUI 来管理 Docker 镜像和容器。在某种程度上,Docker 容器就像一个虚拟机,只是 Docker 容器使用的资源要少得多。在本章的最后,我会推荐了一些资源来学习更多关于 Docker 的知识。
如果你仍然喜欢在本地而不是在 Docker 容器中运行命令行工具,那么你当然可以自己单独安装这些命令行工具。请注意,这是一个非常耗时的过程。附录中列出了本书中使用的所有命令行工具。安装说明仅适用于 Ubuntu。本书中使用的脚本和数据集可以通过克隆本书的 GitHub 仓库得。
为了安装 Docker 镜像,首先需要从 Docker 网站中下载并安装 Docker 本身。安装 Docker 后,你就可以在终端或命令提示符下调用以下命令来下载 Docker 镜像(不要输入入美元符号):
$ docker pull datasciencetoolbox/dsatcl2e
然后你可以运行 Docker 镜像,如下所示:
$ docker run --rm -it datasciencetoolbox/dsatcl2e
现在你处于一个称为 Docker 容器的隔离环境中,它安装了所有必要的命令行工具。如果下面的命令绘制了一头热情的牛,那么这就表示一切工作正常:
$ cowsay "Let's moove\!"
______________
< Let's moove! >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
如果你想在容器和机器中交换数据,你可以为容器可以添加一个卷,这意味着机器中的本地目录将被映射到容器内的一个目录。所以我建议你首先创建一个新目录,然后进入这个新目录,然后在 macOS 或 Linux 上运行以下命令:
$ docker run --rm -it -v "$(pwd)":/data datasciencetoolbox/dsatcl2e
或者在 Windows 上使用命令提示符(也称为cmd
)上运行以下命令:
C:\> docker run --rm -it -v "%cd%":/data datasciencetoolbox/dsatcl2e
或者当你使用 Windows PowerShell 上运行以下命令:
PS C:\> docker run --rm -it -v ${PWD}:/data datasciencetoolbox/dsatcl2e
在上面的命令中,选项-v
指示docker
将当前目录映射到容器内的/data
目录,因此这也是 Docker 容器和机器交换数据的地方。
如果你想要知道更多关于 Docker 镜像的知识,请访问该 网址
当这些都完成后,你可以通过输入exit
命令来关闭 Docker 容器。
在第一章中,我简单的给大家展示了命令行是什么。如果现在你正在运行 Docker 镜像,那么我们就可以真正开始了。在这一节中,我将讨论几个概念和工具,为了能在命令行中轻松地进行数据科学研究,你需要了解这些概念和工具。如果到目前为止,你主要用的都是图形用户界面,那么这次可能是一个相当大的改变。但是不要担心,我会从头开始,然后逐渐进入更高级的主题。
本节不是一个完整的 Unix 课程。我将只解释与做数据科学有关的概念和工具。Docker 镜像的优势之一是很多东西都已经设置好了。如果你想了解更多,请参考本章末尾的进一步阅读部分。
现在我们刚刚进入了一个全新的环境,因此在做任何事情之前,我们都有必要对这个环境有一个大体的了解。该环境大致定义为四层,我将简单的的从上到下的介绍它们。
命令行工具
首先,也是最重要的是我们使用的命令行工具。我们通过输入相应的命令来使用它们。命令行工具有许多种类型(这个将在下一节讨论),常见例子有:ls
,cat
,jq
。
终端
终端是第二个概念,它是我们输入命令的应用。如果你看到书中提到的以下文字:
$ seq 3
1
2
3
然后你也可以跟着在你的终端上输入seq 3
,按下Enter
,结果就会生成一个数字序列。不要输入美元符号$
,它只是告诉你这是一个你可以在终端输入的命,这个美元符号被称为提示符。
Shell
第三层是 Shell。一旦我们输入命令并按下Enter
,终端就将命令发送给 Shell, Shell 是一个解释命令的程序。我使用的是 ZShell,还有许多其他可用的 Shell,比如 Bash 和 Fish。
操作系统
第四层是操作系统,在我们的例子中是 GNU/Linux。Linux 是内核的名字,它是操作系统的核心。内核直接与 CPU、磁盘和其他硬件接触,内核还执行我们的命令行工具。GNU,代表 GNU’s Not UNIX,指的是一套基本工具。Docker 镜像是基于一个特定的 GNU/Linux 发行版,该发行版称为 Ubuntu。
现在你已经对环境有了基本的了解,是时候尝试一些命令了。在你的终端中键入以下内容(不带美元符号),然后按Enter
:
$ pwd
/home/dst
你刚刚执行了一个包含单个命令行工具的命令。工具pwd
输出你当前所在目录的名称。默认情况下,你登录的是你的主目录。
ZShell 种内置的命令行工具cd
允许你导航到不同的目录:
$ cd /data/ch02 # ➊
$ pwd # ➋
/data/ch02
$ cd .. # ➌
$ pwd # ➍
/data
$ cd ch02 # ➎
➊ 导航到目录/data/ch02
。
➋ 打印当前目录。
➌ 导航到父目录。
➍ 再次打印当前目录。
➎ 导航到子目录ch02
。
cd
之后的部分指定你想要去的那个目录。命令后面的值被称为命令行参数或选项。两个点表示父目录。顺便说一下,一个点指的是当前目录。虽然cd .
不会有任何影响,但你仍然会看到一个点被用在其他地方。接下来让我们尝试一个不同的命令:
$ head -n 3 movies.txt
Matrix
Star Wars
Home Alone
这里我们将三个命令行参数传递给head
。第一个是选项。这里我使用了短选项-n
。有时一个短的选项有一个长的变量的意思,现在这种情况下就是--lines
,第二个是属于选项的值,第三个是文件名。这个特定的命令的意思是输出文件/data/ch02/movies.txt
的前三行内容。
我们一直在说术语命令行工具,但是到目前为止也没有解释它的真正含义。我把它作为一个总称,指的是任何可以从命令行执行的东西(图 2.1)。实际上,每个命令行工具都是以下五种类型之一:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uRi0900m-1680148019177)(null)]
图 2.1:命令行工具作为一个总称
我们需要知道命令行之间的区别。Docker 镜像预安装的命令行工具主要包括前两种类型(二进制可执行文件和 Shell 内置程序)。其他三种类型(解释脚本、Shell 函数和别名)允许我们进一步构建我们的数据科学工具箱,从而成为更高效、更高产的数据科学家。
二进制可执行文件
二进制可执行文件是传统意义上的程序,它是通过将源代码编译为机器代码而产生的。这意味着当你在文本编辑器中打开文件时是一个乱码。
Shell 内置工具
Shell 内置工具是 Shell 提供的命令行工具,在我们的例子中是 ZShell(或zsh
),它的内置工具包括cd
和pwd
。不同 Shell 的内置工具可能不同。Shell 内置工具像二进制可执行文件一样不容易检查或更改。
解释脚本
解释脚本是一个可以由二进制可执行文件执行的文本文件。常用的脚本包括:Python、R 和 Bash 脚本。解释脚本的一个很大的优点就是你可以阅读和修改它。下面的脚本可以用 Python 执行,之所以可以被执行,不是因为它的文件扩展名是.py
,而是因为脚本的第一行定义了应该执行它的二进制。
$ bat fac.py
───────┬──────────────────────────────────────────────────────────────
│ File: fac.py
───────┼──────────────────────────────────────────────────────────────
1 │ #!/usr/bin/env python
2 │
3 │ def factorial(x):
4 │ result = 1
5 │ for i in range(2, x + 1):
6 │ result *= i
7 │ return result
8 │
9 │ if __name__ == "__main__":
10 │ import sys
11 │ x = int(sys.argv[1])
12 │ sys.stdout.write(f"{factorial(x)}\n")
───────┴──────────────────────────────────────────────────────────────
这个脚本的作用是计算整数的阶乘,我们可以从命令行调用它,如下所示:
$ ./fac.py 5
120
在第四章中,我们将详细讨论如何使用解释脚本创建可重用的命令行工具。
Shell 函数
在我们的例子中,Shell 函数是由zsh
执行的函数。它们提供了与脚本相似的功能,但是它们通常(但不一定)比脚本小,也更倾向于个人化。下面的命令定义了一个名为fac
的函数,就像上面解释的 Python 脚本一样,它计算我们作为参数传递的整数的阶乘。它通过使用seq
生成一个数字列表,使用paste
将这些数字放在一行中作为分隔符,并将该等式传递给bc
,后者对其求值并输出结果。
$ fac() { (echo 1; seq $1_ | paste -s -d\* - | bc; }
$ fac 5
120
文件~/.zshrc
是 ZShell 的配置文件,也是定义 Shell 函数的好地方,在这里定义之后就一直可用了。
别名
别名就像宏一样。如果你发现自己经常用相同的参数(或部分参数)执行某个命令,你就可以为它定义一个别名来节省时间。当你不断拼错某个命令时,别名也非常有用(Chris Wiggins 维护了一个有用的别名列表)。下面的命令就定义了这样一个别名:
$ alias l='ls --color -lhF --group-directories-first'
$ alias les=less
现在,如果你在命令行上输入以下内容,Shell 将用它的值替换它发现的每个别名:
$ cd /data
$ l
total 40K
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch02/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch03/
drwxr-xr-x 3 dst dst 4.0K Mar 3 10:38 ch04/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch05/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch06/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch07/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch08/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch09/
drwxr-xr-x 4 dst dst 4.0K Mar 3 10:38 ch10/
drwxr-xr-x 3 dst dst 4.0K Mar 3 10:38 csvconf/
$ cd ch02
别名比 Shell 函数简单,因为它们不允许参数。由于参数的原因,无法使用别名定义函数fac
。尽管如此,别名可以让你节省大量的击键次数。像 Shell 函数一样,别名通常在文件.zshrc
中定义。该文件位于你的主目录下,要查看当前定义的所有别名,可以不带参数地运行alias
。试试看,你看到了什么?
在本书中,我们将主要关注最后三种类型的命令行工具:解释脚本、Shell 函数和别名,因为这些类型很容易改变。命令行工具的目的是使你的生活更加轻松,并使你成为更有生产力和效率的数据科学家。你可以通过type
找到命令行工具的类型(它本身是一个 Shell 内置的工具):
$ type -a pwd
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd
$ type -a cd
cd is a shell builtin
$ type -a fac
fac is a shell function
$ type -a l
l is an alias for ls --color -lhF --group-directories-first
type
为pwd
返回了三个命令行工具。在这种情况下,当你输入pwd
时,将使用第一个命令行工具。在下一节中,我们将学习如何组合命令行工具。
因为大多数命令行工具都遵循 Unix 哲学,它们被设计成只做一件事,但是做得非常好。例如,命令行工具grep
用来过滤行数据,wc
用来计数行数据,sort
可以排序行数据。命令行的强大之处在于它能够组合这些小而强大的命令行工具。
命令行的能力是通过管理这些工具的通信流实现的。每个工具都有三个标准通信流:标准输入、标准输出和标准错误。这些通常被简写为stdin``stdout``stderr
。
默认情况下,标准输出和标准错误都被重定向到终端,因此正常输出和任何错误信息都被打印在屏幕上。图 2.2 对pwd
和rev
都进行了说明,如果你运行rev
,你会看到什么都没有发生。这是因为rev
期望有输入,默认情况下,就是在键盘上按下任何键。试着输入一个句子并按下回车键,rev
就会立即对你的输入进行反向响应。你可以按Ctrl+D
来停止发送输入,然后rev
就会停止。
图 2.2:工具的通信流:标准输入(stdin
)、标准输出(stdout
)、标准误差(stderr
)
但是实际上,我们不会使用键盘作为输入源,而是使用其他工具产生的输出和文件的内容。例如,通过curl
,我们可以下载 Lewis Carrol 写的《Alice’s Adventures in Wonderland》这本书,然后用管道把它送到下一个工具(curl 将再第三章讨论)。管道通过用管道操作符|
完成的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FTbZZlk1-1680148019354)(null)]
图 2.3:一个工具的输出通过管道传输到另一个工具
我们可以用管道将curl
的输出连接到grep
,以过滤每行的数据。想象一下,如果我们想看看目录中列出的章节,我们就可以将curl
和grep
结合起来使用,如下所示:
$ curl -s "https://www.gutenberg.org/files/11/11-0.txt" | grep " CHAPTER"
CHAPTER I. Down the Rabbit-Hole
CHAPTER II. The Pool of Tears
CHAPTER III. A Caucus-Race and a Long Tale
CHAPTER IV. The Rabbit Sends in a Little Bill
CHAPTER V. Advice from a Caterpillar
CHAPTER VI. Pig and Pepper
CHAPTER VII. A Mad Tea-Party
CHAPTER VIII. The Queen’s Croquet-Ground
CHAPTER IX. The Mock Turtle’s Story
CHAPTER X. The Lobster Quadrille
CHAPTER XI. Who Stole the Tarts?
CHAPTER XII. Alice’s Evidence
如果我们想知道这本书有多少章节,我们可以使用wc
,它非常擅长计数:
$ curl -s "https://www.gutenberg.org/files/11/11-0.txt" |
> grep " CHAPTER" |
> wc -l # ➊
12
➊ 选项-l
指定wc
应该只输出传递给它的行数。默认情况下,它还返回字符数和字数。
你可以把管道操作看成是一种自动的复制和粘贴。一旦你掌握了使用管道操作符组合工具的技巧,你会发现它几乎没有任何限制。
除了将一个工具的输出输送到另一个工具外,你还可以将其保存到一个文件中。该文件将被保存在当前目录下,除非给出完整的路径。这被称为输出重定向,其工作原理如下:
$ curl "https://www.gutenberg.org/files/11/11-0.txt" | grep " CHAPTER" > chapter
s.txt
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 170k 100 170k 0 0 183k 0 --:--:-- --:--:-- --:--:-- 184k
$ cat chapters.txt
CHAPTER I. Down the Rabbit-Hole
CHAPTER II. The Pool of Tears
CHAPTER III. A Caucus-Race and a Long Tale
CHAPTER IV. The Rabbit Sends in a Little Bill
CHAPTER V. Advice from a Caterpillar
CHAPTER VI. Pig and Pepper
CHAPTER VII. A Mad Tea-Party
CHAPTER VIII. The Queen’s Croquet-Ground
CHAPTER IX. The Mock Turtle’s Story
CHAPTER X. The Lobster Quadrille
CHAPTER XI. Who Stole the Tarts?
CHAPTER XII. Alice’s Evidence
在这里,我们将grep
的输出保存在/data/ch02
目录下一个名为chapters.txt
的文件中。如果这个文件还不存在,它将被创建。如果这个文件已经存在,其内容将被覆盖。图 2.4 说明了输出重定向在概念上是如何工作的。注意,标准错误仍然被重定向到终端:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-35jdchrL-1680148019207)(null)]
图 2.4:工具的输出可以重定向到一个文件
你还可以使用>>
将输出附加到文件中,这意味着输出被添加到原始内容之后:
$ echo -n "Hello" > greeting.txt
$ echo " World" >> greeting.txt
工具echo
输出你指定的值。代表换行符的-n
选项指定echo
不输出尾随换行符\n
。
如果你需要存储中间结果,将输出保存到文件中是非常有用的,例如在以后的阶段继续分析。要再次使用文件greeting.txt
的内容,我们可以使用cat
,它读取一个文件并打印它。
$ cat greeting.txt
Hello World
$ cat greeting.txt | wc -w # ➊
2
➊ -w
选项表示wc
只统计字数。
使用小于号(<
)可以获得相同的结果:
$ < greeting.txt wc -w
2
通过小于号(<
)这种方式,你直接将文件传递给wc
的标准输入,而不需要运行一个额外的进程。图 2.5 说明了这两种方式的工作原理。同样,最终的输出也是一样的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6X1nBfvn-1680148019382)(null)]
图 2.5:使用文件内容作为输入的两种方式
像许多命令行工具一样,wc
允许将一个或多个文件名指定为参数。例如:
$ wc -w greeting.txt movies.txt
2 greeting.txt
11 movies.txt
13 total
注意,在这种情况下,wc
也输出文件的名称。
你可以通过将任何工具的输出重定向到一个名为/dev/null
的特殊文件来保留它。我经常这样做来保留错误消息(见图 2.6 的说明)。下面的内容将导致cat
产生一个错误信息,因为它找不到404.txt
这个文件:
$ cat movies.txt 404.txt
Matrix
Star Wars
Home Alone
Indiana Jones
Back to the Future
/usr/bin/cat: 404.txt: No such file or directory
你可以将标准错误重定向到/dev/null
,如下所示:
$ cat movies.txt 404.txt 2> /dev/null # ➊
Matrix
Star Wars
Home Alone
Indiana Jones
Back to the Future
➊ 2
指标准错误
图 2.6:将stderr
重定向到/dev/null
注意不要从同一个文件中读出和写入。如果你这样做,你会得到一个空文件。这是因为输出被重定向的工具会立即打开该文件进行写入,从而将其清空。这有两个解决办法:(1)写到一个不同的文件,然后用mv
重命名;(2)使用sponge
,它在写到一个文件之前吸收了所有的输入。图 2.7 说明了这是如何工作的:
图 2.7:除非你使用sponge
,否则你不能在一个管道中读取和写入同一个文件
例如,假设你已经使用dseq
生成了一个文件dates.txt
,现在你想使用nl
添加行号。如果运行下面的代码,文件dates.txt
将会是空的。
$ dseq 5 > dates.txt
$ < dates.txt nl > dates.txt
$ bat dates.txt
───────┬────────────────────────────────────────────────────────────────────────
│ File: dates.txt
───────┴────────────────────────────────────────────────────────────────────────
所以说你可以使用我刚刚描述的解决方法之一:
$ dseq 5 > dates.txt
$ < dates.txt nl > dates-nl.txt
$ bat dates-nl.txt
───────┬────────────────────────────────────────────────────────────────────────
│ File: dates-nl.txt
───────┼────────────────────────────────────────────────────────────────────────
1 │ 1 2022-03-04
2 │ 2 2022-03-05
3 │ 3 2022-03-06
4 │ 4 2022-03-07
5 │ 5 2022-03-08
───────┴────────────────────────────────────────────────────────────────────────
$ dseq 5 > dates.txt
$ < dates.txt nl | sponge dates.txt
$ bat dates.txt
───────┬────────────────────────────────────────────────────────────────────────
│ File: dates.txt
───────┼────────────────────────────────────────────────────────────────────────
1 │ 1 2022-03-04
2 │ 2 2022-03-05
3 │ 3 2022-03-06
4 │ 4 2022-03-07
5 │ 5 2022-03-08
───────┴────────────────────────────────────────────────────────────────────────
作为数据科学家,我们处理大量数据。这些数据通常存储在文件中。了解如何在命令行上处理文件(以及它们所在的目录)是很重要的。使用 GUI 可以做的每一个动作,都可以用命令行工具来完成(等等)。在这一节中,我将介绍列举、创建、移动、复制、重命名和删除文件和目录的最重要的方法。
用ls
可以列出一个目录的内容。如果不指定目录,它会列出当前目录的内容。我更喜欢ls
有一个长列表格式,并且目录和文件分组,目录在前。我使用别名l
,而不是每次都输入相应的选项。
$ ls /data/ch10
alice.txt count.py count.R __pycache__ Untitled1337.ipynb
$ alias l
l='ls --color -lhF --group-directories-first'
$ l /data/ch10
total 180K
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 __pycache__/
-rw-r--r-- 1 dst dst 164K Mar 3 10:38 alice.txt
-rwxr--r-- 1 dst dst 408 Mar 3 10:38 count.py*
-rw-r--r-- 1 dst dst 460 Mar 3 10:38 count.R
-rw-r--r-- 1 dst dst 1.7K Mar 3 10:38 Untitled1337.ipynb
你已经看到了我们如何通过使用>
或>>
重定向输出来创建新文件。如果你需要将文件移动到不同的目录,你可以使用mv
:
$ mv hello.txt /data/ch02
你也可以使用mv
重命名文件:
$ cd data
$ mv hello.txt bye.txt
你也可以重命名或移动整个目录。如果你不再需要一个文件,你用rm
删除它:
$ rm bye.txt
如果你想要删除整个目录及其所有内容,请指定-r
选项,它代表递归:
$ rm -r /data/ch02/old
如果要复制一个文件,使用cp
。这对于创建备份非常有用:
$ cp server.log server.log.bak
你可以使用mkdir
创建目录:
$ cd /data
$ mkdir logs
$ l
total 44K
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:39 ch02/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch03/
drwxr-xr-x 3 dst dst 4.0K Mar 3 10:38 ch04/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch05/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch06/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch07/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch08/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:38 ch09/
drwxr-xr-x 4 dst dst 4.0K Mar 3 10:38 ch10/
drwxr-xr-x 3 dst dst 4.0K Mar 3 10:38 csvconf/
drwxr-xr-x 2 dst dst 4.0K Mar 3 10:39 logs/
使用命令行工具来管理你的文件,一开始可能很可怕,因为你没有文件系统的图形概览来提供即时反馈。有一些可视化的文件管理器可以帮助解决这个问题,比如 GNU Midnight Commander、Ranger 和 Vifm。这些都没有安装在 Docker 镜像中,但你可以通过运行 sudo apt install,然后选择 mc、ranger 或 vifm,自己安装一个。
上面所有的命令行工具都接受代表 verbose 的-v
选项,这样它们就可以输出正在发生的事情。例如:
$ mkdir -v backup
/usr/bin/mkdir: created directory 'backup'
$ cp -v * backup
/usr/bin/cp: -r not specified; omitting directory 'backup'
/usr/bin/cp: -r not specified; omitting directory 'ch02'
/usr/bin/cp: -r not specified; omitting directory 'ch03'
/usr/bin/cp: -r not specified; omitting directory 'ch04'
/usr/bin/cp: -r not specified; omitting directory 'ch05'
/usr/bin/cp: -r not specified; omitting directory 'ch06'
/usr/bin/cp: -r not specified; omitting directory 'ch07'
/usr/bin/cp: -r not specified; omitting directory 'ch08'
/usr/bin/cp: -r not specified; omitting directory 'ch09'
/usr/bin/cp: -r not specified; omitting directory 'ch10'
/usr/bin/cp: -r not specified; omitting directory 'csvconf'
/usr/bin/cp: -r not specified; omitting directory 'logs'
除了mkdir
之外的所有工具也接受-i
选项,它代表“交互式”,这样工具就会要求你确认。例如:
$ rm -i *
zsh: sure you want to delete all 12 files in /data [yn]? n
有时,一个工具或工具序列产生了太多的输出,无法包含在书中。与其手动改变这样的输出,我更喜欢通过一个辅助工具的管道将其透明化。你不一定要这样做,尤其是如果你对完整的输出感兴趣。
以下是我用来管理输出的工具:
我们可以使用trim
来限制输出给定的高度和宽度,默认情况下,输出被修剪为 10 行和终端的宽度,但也可以传递一个负数以禁止修剪高度和/或宽度。例如:
$ cat /data/ch07/tips.csv | trim 5 25
bill,tip,sex,smoker,day,…
16.99,1.01,Female,No,Sun…
10.34,1.66,Male,No,Sun,D…
21.01,3.5,Male,No,Sun,Di…
23.68,3.31,Male,No,Sun,D…
… with 240 more lines
我用来管理输出的其他工具有:head
、tail
、fold
、paste
和column
,附录中包含了每种方法的示例。
如果输出是逗号分隔的值,我通常通过csvlook
将它转换成一个好看的表格。如果你运行csvlook
,你将看到完整的表格。我通过trim
重新定义了csvlook
,这样表格就缩短了:
$ which csvlook
csvlook() {
/usr/bin/csvlook "$@" | trim | sed 's/- | -/──┼──/g;s/| -/├──/g;s/- |/──
┤/;s/|/│/g;2s/-/─/g'
}
$ csvlook /data/ch07/tips.csv
│ bill │ tip │ sex │ smoker │ day │ time │ size │
├───────┼───────┼────────┼────────┼──────┼────────┼──────┤
│ 16.99 │ 1.01 │ Female │ False │ Sun │ Dinner │ 2 │
│ 10.34 │ 1.66 │ Male │ False │ Sun │ Dinner │ 3 │
│ 21.01 │ 3.50 │ Male │ False │ Sun │ Dinner │ 3 │
│ 23.68 │ 3.31 │ Male │ False │ Sun │ Dinner │ 2 │
│ 24.59 │ 3.61 │ Female │ False │ Sun │ Dinner │ 4 │
│ 25.29 │ 4.71 │ Male │ False │ Sun │ Dinner │ 4 │
│ 8.77 │ 2.00 │ Male │ False │ Sun │ Dinner │ 2 │
│ 26.88 │ 3.12 │ Male │ False │ Sun │ Dinner │ 4 │
… with 236 more lines
我使用bat
来显示文件的内容,其中行号和语法会突出显示。例如源代码:
$ bat /data/ch04/stream.py
───────┬────────────────────────────────────────────────────────────────────────
│ File: /data/ch04/stream.py
───────┼────────────────────────────────────────────────────────────────────────
1 │ #!/usr/bin/env python
2 │ from sys import stdin, stdout
3 │ while True:
4 │ line = stdin.readline()
5 │ if not line:
6 │ break
7 │ stdout.write("%d\n" % int(line)**2)
8 │ stdout.flush()
───────┴────────────────────────────────────────────────────────────────────────
有时,当我想明确指出文件中的空格、制表符和换行符时,我会添加-A
选项。
有时将中间输出写到文件中很有用。这允许你在管道中的任何步骤完成后对其进行检查。你可以在你的管道中插入工具tee
。我经常用它来检查最终输出的一部分,同时将完整的输出写入文件(见图 2.8)。在这个例子中,完整的输出被写入even.txt
,前 5 行被使用trim
打印:
$ seq 0 2 100 | tee even.txt | trim 5
0
2
4
6
8
… with 46 more lines
图 2.8:使用tee
将中间输出写入文件
最后,为了插入由命令行工具生成的图片(除了屏幕截图和图表之外的每张图片),我使用了display
。但是如果你运行display
,你会发现它不起作用。在第七章中,我介绍了四个选项,让你从命令行中显示生成的图像。
当你在命令行中摸索时,可能会需要帮助,即使是最有经验的用户在某些时候也需要帮助。我们不可能记住所有不同的命令行工具及其可能的参数。幸运的是,命令行提供了几种获得帮助的方法。
获得帮助最重要的命令或许是man
,是手动的简称。它包含大多数命令行工具的信息。如果我忘记了工具tar
的选项,这种情况经常发生,我只需使用以下命令访问它的手册页:
$ man tar | trim 20
TAR(1) GNU TAR Manual TAR(1)
NAME
tar - an archiving utility
SYNOPSIS
Traditional usage
tar {A|c|d|r|t|u|x}[GnSkUWOmpsMBiajJzZhPlRvwo] [ARG...]
UNIX-style usage
tar -A [OPTIONS] ARCHIVE ARCHIVE
tar -c [-f ARCHIVE] [OPTIONS] [FILE...]
tar -d [-f ARCHIVE] [OPTIONS] [FILE...]
tar -t [-f ARCHIVE] [OPTIONS] [MEMBER...]
tar -r [-f ARCHIVE] [OPTIONS] [FILE...]
… with 1147 more lines
并非每个命令行工具都有手册页。以cd
为例:
$ man cd
No manual entry for cd
对于像cd
这样的 Shell 内置,你可以参考zshbuildins
手册页:
$ man zshbuiltins | trim
ZSHBUILTINS(1) General Commands Manual ZSHBUILTINS(1)
NAME
zshbuiltins - zsh built-in commands
SHELL BUILTIN COMMANDS
Some shell builtin commands take options as described in individual en‐
tries; these are often referred to in the list below as `flags' to
avoid confusion with shell options, which may also have an effect on
the behaviour of builtin commands. In this introductory section, `op‐
… with 2735 more lines
按/
可以搜索,按q
可以退出。尝试为cd
找到合适的部分。
较新的命令行工具通常也没有手册页。在这种情况下,最好的办法是使用--help
(或-h
)选项调用工具。例如:
$ jq --help | trim
jq - commandline JSON processor [version 1.6]
Usage: /usr/bin/jq [options] [file...]
/usr/bin/jq [options] --args [strings...]
/usr/bin/jq [options] --jsonargs [JSON_TEXTS...]
jq is a tool for processing JSON inputs, applying the given filter to
its JSON text inputs and producing the filter's results as JSON on
standard output.
… with 37 more lines
指定--help
选项也适用于命令行工具,比如cat
。但是,相应的手册页通常会提供更多信息。如果在尝试了这三种方法后,你仍然有不明白的地方,那为啥不 Google 一下呢。在附录中,列出了本书中使用的所有命令行工具。除了如何安装每个命令行工具,它还显示了如何获得帮助。
手册页可能非常冗长,难以阅读。工具tldr
是一个由社区维护的命令行工具帮助页面的集合,旨在成为传统手册页面的一个更简单、更易用的补充。下面是一个显示tar
的tldr
页面的示例:
$ tldr tar | trim 20
tar
Archiving utility.
Often combined with a compression method, such as gzip or bzip2.
More information: https://www.gnu.org/software/tar.
- [c]reate an archive and write it to a [f]ile:
tar cf target.tar file1 file2 file3
- [c]reate a g[z]ipped archive and write it to a [f]ile:
tar czf target.tar.gz file1 file2 file3
- [c]reate a g[z]ipped archive from a directory using relative paths:
tar czf target.tar.gz --directory=path/to/directory .
- E[x]tract a (compressed) archive [f]ile into the current directory [v]erbos…
tar xvf source.tar[.gz|.bz2|.xz]
- E[x]tract a (compressed) archive [f]ile into the target directory:
… with 12 more lines
如你所见,tldr
没有像man
经常做的那样按字母顺序列出许多选项,而是通过给你一个实际例子。
在本章中,你学习了如何通过安装 Docker 镜像来获得所有需要的命令行工具。我还介绍了一些基本的命令行概念以及如何获得帮助。现在你已经具备了所有必要的要素,也已经为 OSEMN 数据科学模型的第一步做好了准备:获取数据。