附录 C 学习命令行
有一个强大的开发工具,就是只用命令行来控制计算机的能力。无论你用的是哪种操作系统,懂得直接与计算机交互的方法,可以让你的数据处理任务和编程任务事半功倍。我们并不是说你要成为系统管理员,但擅于通过命令行来控制计算机是很有用的。
作为一名开发人员,最有成就感的事情之一就是能够对遇到的系统问题和代码问题进行调试。通过命令行理解计算机的运行原理,可以让你深入理解这些问题。如果你遇到了系统错误,并使用本书学到的调试技巧,你可能会更了解自己的计算机和用到的操作系统,也更了解如何用命令行更好地交互。在 Python 代码中遇到系统错误时,你就会在调试并解决这些问题时快人一步。
本附录中我们会讲到 bash(在 Mac 和许多 Linux 上使用)的基础知识,也会讲到 Windows 上 cmd 和 PowerShell 程序的基础知识。我们这里只是做一个简要的介绍,但我们建议你继续深入学习。在每一小节我们都给出了进一步阅读的建议。
C.1 bash
如果你用的是基于 bash 的命令行,你在 C.1.1 节学到的内容也同样适用于任意基于 bash 的客户端,这和你当前使用的操作系统无关。太酷了! bash 是一种功能强大的 shell 语言(或命令行语言)。我们开始学习 bash,首先来看如何在计算机中浏览文件。
C.1.1 跳转命令
在命令行中浏览计算机可以帮你理解用 Python 如何做到这一点。停留在终端或文本编辑器中,可以让你保持专注。
我们首先来看基本命令。打开终端。打开的终端可能会位于 ~
文件夹,代表你的 home 目录。如果你用的是 Linux,home 目录可能位于 <homeyour_computer_name>。如果你用的是 Mac,home 目录可能位于 Users<your_name>。想要查看你所在的文件夹,可以输入:
pwd
你应该会看到像这样的输出:
Userskatharine
或者像这样:
homekatharine
pwd
代表“打印工作目录”(print working directory)。你让 bash 告诉你当前所在的文件夹(或目录)。如果你是第一次学习用命令行跳转,那么这条命令很有用,特别是你想再次确认自己是否位于正确的文件夹中时。
另一个有用的命令用来查看文件夹中都有哪些文件。想要查看当前工作目录中都有哪些文件,输入:
ls
你应该会看到像这样的输出:
Desktop/
Documents/
Downloads/
my_doc.docx
...
具体内容可能会有所不同,颜色也可能不同,这与你的操作系统有关。ls
的含义是“列出清单”(list)。在调用 ls
时还可以指定额外参数,叫作标记(flag)。这些参数会改变输出的内容。试一下这个命令:
ls -l
输出应该有许多列,最后一列与只输入 ls
的输出相同。-l
标记给出了目录的详细(长)内容,其中包括所包含的文件和目录的数目,以及每一个文件和目录的权限、创建者的名字、组所有权、大小和最后修改日期。下面给出一个实例:
drwxr-xr-x 2 katharine katharine 4096 Aug 20 2014 Desktop
drwxr-xr-x 22 katharine katharine 12288 Jul 20 18:19 Documents
drwxr-xr-x 26 katharine katharine 24576 Sep 16 11:39 Downloads
这些细节可以帮你发现与权限有关的问题,还可以查看文件大小和其他信息。你还可以向 ls
传入任意目录,它都可以列出里面的内容。试着查看下载文件夹的内容(输入以下代码):
ls -l ~/Downloads
你会看到与前面类似的很长的输出,但列出的是 Downloads 文件夹下的所有文件和目录。
现在你学会了如何列出不同文件夹下的文件,下面我们来学习如何改变当前所在文件夹。我们利用 cd
命令来“改变目录”(change directory)。试着输入:
cd ~/Downloads
现在用 pwd
查看位于哪个文件夹,用 ls
查看文件夹中的文件,你应该会发现正位于 Downloads 文件夹下。如果你想回到主文件夹的话,应该怎么做?我们知道主文件夹是上一级文件夹。你可以用 ..
跳转到上一级文件夹。试着输入:
cd ..
现在你回到了主文件夹。在 bash 中,..
的意思是“跳转到上一级目录”。你还可以连用两次,跳转到上两级目录,像这样:cd ../..
。
在命令行中跳转目录或选择文件时,你应该可以用 Tab 键自动补全文件名和文件夹名。对于你想选择的文件或文件夹,先输入名字的第一个字母或前两个字母,然后只需按下 Tab 键,你应该会看到不同的匹配选择(帮你完成名字的拼写)。如果没有类似名字的其他文件,命令行会将名字自动补全。这个方法可以节省很多打字的时间!
现在你应该更习惯于用命令行来跳转目录。下面我们将学习如何用命令行移动文件和修改文件。
C.1.2 修改文件
利用 bash 移动文件、复制文件和创建文件都很简单。我们先来看创建新文件。首先,跳转到 home 目录(cd ~
)。然后输入下列内容:
touch test_file.txt
然后再继续输入 ls
。你应该会看到有一个叫作 test_file.txt 的新文件。touch
可以用来创建新文件。这个命令会寻找叫这个名字的文件。如果有这个文件的话,会改变最后一次修改的时间戳,但不会修改文件内容;如果文件不存在,会创建这个文件。
Atom shell 命令
如果你的文本编辑器是 Atom.io(https://atom.io/),你可以利用下面这个命令轻松将这个文件(或任何文件)用 Atom 打开:
atom test_file.txt
如果报错的话,你可能没有安装命令行选项。安装方法是:按 Shift-Cmd-P 键打开命令面板,然后运行 Install Shell Commands 命令。
想要查看Atom 所有命令行选项,可以输入
atom --help
。
对于之前创建的文件,我们试着将其复制到下载文件夹中:
cp test_file.txt ~/Downloads
这里我们的意思是:“将 test_file.txt 复制到 ~/Downloads 文件夹中。”bash 知道 ~/Downloads 是一个文件夹,所以会自动将文件复制到那个文件夹里面。如果我们想要在复制文件的同时改变文件名,可以这么做:
cp test_file.txt ~/Downloads/my_test_file.txt
这个命令的作用是让 bash 将测试文件复制到下载文件夹中,并将复制后的文件命名为 my_test_file.txt。现在你的下载文件夹中应该有测试文件的两份副本:一个用的是原来的名字,一个用的是新名字。
如果你需要多次运行同一个命令,只需按向上键,在命令行历史中查找。如果你想查看最近所有的命令行历史,可以输入
history
。
有时你并不想复制文件,而是想要移动文件或重命名文件。在 bash 中,我们可以用同一个命令来移动文件和重命名文件:mv
。我们首先对在主文件夹中创建的文件进行重命名:
mv test_file.txt empty_file.txt
这里我们告诉 bash:“将名为 test_file.txt 的文件移动到名为 empty_file.txt 的文件。”输入 ls
,你应该会看到已经没有 test_file.txt 了,但现在有一个 empty_file.txt。我们只是利用“移动”来对文件重命名。我们还可以利用 mv
在文件夹之间移动文件:
mv ~/Downloads/test_file.txt .
这里我们的意思是:“将下载文件夹中的 test_file.txt 移动到这里。”在 bash 中,.
代表你的工作目录(就像 ..
代表当前目录的“上一级”文件夹一样)。现在输入 ls,你应该可以看到主文件夹中又有一个 test_file.txt 文件了。你还可以输入 ls ~/Downloads
,现在这个文件已经不在下载文件夹中了。
最后,你可以用命令行删除文件。你可以用 rm
(remove)命令来做到这一点。试着输入:
rm test_file.txt
现在再输入 ls
,你会发现 test_file.txt 已经从文件夹中删掉了。
与用鼠标删除文件不同,用命令行删除文件是真正的删除。没有“回收站”可以恢复文件,所以使用
rm
时一定要小心,对你的计算机和代码一定要定期按时备份。
现在你知道利用 bash 如何移动、重命名、复制和删除文件,下面我们继续学习在命令行中运行文件。
C.1.3 运行文件
利用 bash 运行文件是相当简单的。在第 3 章中你可能已经学过运行 Python 文件,你只需运行:
python my_file.py
其中 my_file.py 是一个 Python 文件。
对于编程用到的大多数语言来说,只输入语言的名字(
python
、ruby
、R
)和文件名(并带有正确的文件路径或文件位置)就可以运行。如果你在用某种语言运行文件时遇到问题,我们建议以语言的名字和“命令行选项”(command-line options)为关键词在网络上进行搜索。
作为一名 Python 开发者,你还会用到其他运行命令。表 C-1 中给出了其中一些命令,你可以先了解一下,在安装和运行外部库时可能会用到。
表C-1:bash中的运行命令
命令 | 使用案例 | 更多文档 |
---|---|---|
sudo
|
以 sudo 或(超级)用户的身份运行下面的命令。在修改文件系统的核心部分或安装外部包时通常需要用到 sudo
| https://en.wikipedia.org/wiki/Sudo |
bash
| 运行 bash 文件,或回到 bash shell | http://ss64.com/bash/ |
./configure
| 运行软件包的配置设定(从源代码安装软件包的第一步) | https://en.wikipedia.org/wiki/GNU_build_system#GNU_Autoconf |
make
|
配置完成后运行 makefile ,编译代码准备安装(从源代码安装软件包的第二步)
| http://www.computerhope.com/unix/umake.htm |
make install
|
运行 make 编译好的代码,将软件包安装到计算机中(从源代码安装软件包的第三步)
| http://www.codecoffee.com/tipsforlinux/articles/27.html |
wget
| 访问 URL,并下载 URL 里包含的文件(适用于下载软件包或文件) | http://www.gnu.org/software/wget/manual/wget.html |
chown
|
改变文件或文件夹的所有权。通常与 chgrp 一起使用,用来改变文件的所属群组。如果你需要移动文件让另一个用户可以运行这些文件,那么这个命令是很有用的
| http://linux.die.net/man/1/chown |
chmod
| 改变文件或文件夹的权限,通常是使文件可执行,或对另一类用户或用户组可见 | http://ss64.com/bash/chmod.html |
在使用命令行的过程中,你可能会遇到其他各种各样的命令和文档。我们建议你花点时间去学习、使用并提问。bash 是一种不同的语言,需要慢慢去学习它的特点和用法。最后,我们要向你介绍利用 bash 来搜索文件或文件内容。
C.1.4 利用命令行进行搜索
在 bash 中,搜索文件和在文件内搜索都相对简单,也有很多种方法。我们将向你展示几种方法。首先,我们将会用一个命令搜索文件中的文本。我们先用 wget
下载一个文件:
wget http://corpus.byu.edu/glowbetext/samples/text.zip
这应该会下载一个文本语料库,我们可以在里面搜索。将文本解压到一个新文件夹,只需输入:
mkdir text_samples
unzip text.zip text_samples/
现在在新文件夹 text_samples 中应该有许多文本语料库文件。输入 cd text_samples
切换到这个目录中。我们利用一个叫作 grep
的工具来搜索这些文件的内容:
grep snake *.txt
这里的命令是告诉 bash,在这个文件夹所有以 .txt 结尾的文件中搜索字符串 snake。在 7.2.6 节可以学到更多关于通配符的内容,但 *
几乎总可以用作通配符,意思是“任意匹配的字符串”。
运行上面的命令,你应该会看到输出大量匹配的文本。grep
会返回所有匹配文件中包含目标字符串的所有行。比如当你要修改某个函数,想在一个很大的仓库中找到包含这个函数的文件时,这一命令特别有用。如果你想打印出前后的几行,还可以向 grep
传入额外的参数和选项。
想查看任意 bash 命令的选项,只需先输入该命令,然后输入空格和
--help
即可。输入grep --help
,然后阅读grep
的一些额外选项和特性。
另一个简洁的工具是 cat
。它只是打印出你指定的文件内容。这个命令很有用,特别是需要将输出内容通过“管道”(pipe)传递到其他地方时。在 bash 中,|
字符可以将你希望对文件或文本执行的一系列操作合并在一起。例如,我们将其中一个文件的内容 cat
出来,然后用 grep
在输出中搜索:
cat w_gh_b.txt | grep network
首先返回的是 w_gh_b.txt 文件的所有文本,然后通过“管道”将输出传递给 grep
,然后在其中搜索单词 network 并在命令行中返回包含该词的文本行。
我们还可以对 bash 历史记录做同样的管道操作。试着输入:
history | grep mv
这一命令可以帮你找到在学习 bash 的过程中用过的命令并复用,你可能已经不记得这些命令了。
我们来进一步学习搜索,学习如何查找文件。首先,我们将用到一个叫作 find
的命令,用来查找匹配的文件名,还可以遍历所有子目录并查找匹配的文件。我们在当前文件夹及其子文件夹中找出所有文本文件:
find . -name "*.txt" -type f
这一命令的作用是,(在这个文件夹及其所有子文件夹中)寻找相应的文件,文件名以 .txt 结尾,文件类型为 f(标准文件,而不是目录,目录的类型符号为 d)。你应该会看到输出许多匹配的文件名。下面,我们将这些文件通过管道传递给 grep
命令:
find . -name "*.txt" -type f | xargs grep neat
这里我们让 bash 做的是,“找到与上面相同的文本文件,然后在这些文件中搜索单词 neat”。我们用到了 xargs
命令(https://en.wikipedia.org/wiki/Xargs),这样才能将 find
的输出通过管道正确地传递给 grep
。不是所有的管道操作都需要用到 xargs
,但当 find
命令的输出结果不完全相同时,这一命令十分有用。
你已经学会搜索和查找的一些实用技巧,特别是你要处理的代码和项目越来越庞大、越来越复杂时,这些技巧尤其有用。关于这一话题,我们还为你提供了更多资源和阅读材料。
C.1.5 更多资源
在互联网上有许多优秀的 bash 学习资源(http://wiki.bash-hackers.org/scripting/tutoriallist)。Linux 文档计划(http://www.tldp.org/LDP/Bash-Beginners-Guide/html/)中也有许多适合初学者的优秀教程,里面会讲到一些高级的 bash 编程知识。O'Reilly 出版了一本很棒的 bash Cookbook(http://shop.oreilly.com/product/9780596526788.do),你也可以用这本书开始学习。
C.2 Windows cmd/PowerShell
Windows 命令行(现在再加上 PowerShell,https://en.wikipedia.org/wiki/Windows_PowerShell),或者叫 cmd,是一个功能强大的基于 DOS 的程序。在不同版本的 Windows 和 Windows 服务器中,语法是完全相同的。无论你学的是 Python 还是其他语言,学会这些语法都可以让你成为一个更加优秀的程序员。
C.2.1 跳转命令
用 cmd 浏览文件非常简单。首先打开 cmd 程序查看当前目录。输入:
echo %cd%
这个命令的作用是,告诉 cmd 你想要返回(或输出)%cd%,即当前目录(current directory)。你应该会看到像这样的输出:
C:\Users\Katharine>
想列出当前目录的所有文件,输入以下代码:
dir
你应该会看到类似这样的输出:
13.03.2015 16:07 <DIR> .ipython
11.09.2015 19:05 <DIR> Contacts
11.09.2015 19:05 <DIR> Desktop
11.09.2015 19:05 <DIR> Documents
11.09.2015 19:05 <DIR> Downloads
11.09.2015 19:05 <DIR> Favorites
10.02.2014 15:15 <DIR> Intel
11.09.2015 19:05 <DIR> Links
11.09.2015 19:05 <DIR> Music
11.09.2015 19:05 <DIR> Pictures
13.03.2015 16:26 <DIR> pip
11.09.2015 19:05 <DIR> Saved Games
dir
也有许多可用的选项(http://ss64.com/nt/dir.html),可以排序、分组或显示更多信息。我们来看一下 Desktop 文件夹。
dir Desktop /Q
我们让 cmd 显示 Desktop 目录中的所有文件,以及这些文件的所有者。你应该会看到文件名的前半部分是每个文件的所有者(比如 MY-LAPTOP\Katharine\backupPDF
)。在查看文件夹和文件时这一命令非常有用。还有许多好用的选项,可以显示子文件夹,或者按最后一次修改的时间戳排序。
输入下列代码跳转到 Desktop 文件夹:
chdir Desktop
现在输入 echo %cd%
查看当前目录,你应该会发现与之前的不同。想跳转到上一级文件夹,只需输入 ..
。例如,如果我们想跳转到当前目录的上一级文件夹,可以输入:
chdir ..
你还可以把多个“上一级文件夹”符号连起来(chdir ....
可以跳转到上两级文件夹,以此类推)。根据你的文件结构不同,如果当前文件夹没有上一级目录的话,你可能会得到一个错误(比如你位于文件系统的根目录下)。
想返回 home 目录,只需输入:
chdir %HOMEPATH%
你应该回到了我们开始所在的第一个文件夹。现在我们可以用 cmd 在目录间跳转,下面我们继续学习创建、复制和修改文件。
C.2.2 修改文件
首先,我们来创建一个可用于修改的新文件:
echo "my awesome file" > my_new_file.txt
用 dir
查看文件夹中的文件,现在你应该可以看到 my_new_file.txt。在文本编辑器中打开这个文件,你可以看到文件里面写的是“my awesome file”。如果你用的是 Atom,你可以在 cmd 中直接打开 Atom(参见 C.1.2 节)。
有了这个文件,我们试着将其复制到一个新文件夹中:
copy my_new_file.txt Documents
现在用下列命令列出 Documents 文件夹中所有文件:
dir Documents
我们应该会看到,已经将 my_new_file.txt 成功复制到这里。
你可以用 Tab 键自动补全文件名和路径,简化输入。试着输入
copy my
,然后按 Tab 键。cmd 应该能够猜出你想输入的是 my_new_file.txt 文件,自动补全文件名。
我们还想移动文件或重命名文件。想用 cmd 移动文件,我们可以用 move
命令。试着输入:
move Documents\my_new_file.txt Documents\my_newer_file.txt
如果现在列出 Documents 目录下的文件,你应该会发现没有 my_new_file.txt 了,只有一个 my_newer_file.txt。move
可用于重命名文件(正如上面我们所做的那样)或者移动文件或文件夹。
最后,你可能想要删除不需要的文件。想用 cmd 做到这一点,你可以用 del
命令。试着输入:
del my_new_file.txt
现在查看当前文件夹下的文件,你应该看不到 my_new_file.txt 了。注意,这个命令会完全删除文件。只有在你完全不需要这个文件时才能用这个命令。定期做硬盘备份是很有用的,以防出现任何问题。
我们已经学过了修改文件,下面我们来学习如何在 cmd 中运行文件。
C.2.3 运行文件
想要在 Windows cmd 中运行文件,通常需要输入语言的名字,然后输入文件路径。例如,想运行一个 Python 文件,你需要输入:
python my_file.py
只要 my_file.py 位于同一文件夹下,就会运行这个文件。只需在 cmd 中输入 .exe 文件的全名和路径,然后按 Enter 键,就可以运行这个文件。
与安装 Python 一样,你需要检查安装好的可执行文件的安装包和文件路径是否包含在
Path
变量中(详情可查阅 1.2.2 节)。这个变量为 cmd 保存许多可执行字符串。
想了解更多强大的命令行运行命令,我们推荐学习 Windows PowerShell——一种强大的脚本语言,用来编写脚本并用简单的命令行来运行这些脚本。计算机世界(Computerworld)有一篇很好的 PowerShell 入门文章(http://www.computerworld.com/article/2512066/microsoft-windows-introduction-to-windows-powershell.html)。
想要在命令行中运行安装好的程序,你可以使用 start
命令。试着输入:
start "" "http://google.com"
这个命令应该会打开你的默认浏览器,然后跳转到 Google 首页。更多内容可查阅 start
命令的文档(https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/start.mspx?mfr=true)。
我们已经学习了用命令行如何运行文件,下面研究如何搜索和查找计算机中的文件和文件夹。
C.2.4 利用命令行进行搜索
首先下载一个可用的语料库。如果你用的是 Windows Vista 或更新的版本,你应该能够运行 PowerShell 命令。试着输入下列命令来加载 PowerShell:
powershell
你应该会看到类似这样的新提示符:
Windows PowerShell
...
PS C:\Users\Katharine>
现在我们已经进入了 PowerShell,我们来下载一个用于查找的文件(注意,这两行命令应该在同一行中输入,被分成两行是为了适应页面宽度):
Invoke-WebRequest -OutFile C:\Downloads\text.zip
http://corpus.byu.edu/glowbetext/samples/text.zip
如果你安装的 PowerShell 不是 3.0 版或更高版本,上面这个命令会报错。如果有报错的话,尝试输入下面这个命令,可适用于更早版本的 PowerShell:
Invoke-WebRequest -OutFile C:\Downloads\text.zip
http://corpus.byu.edu/glowbetext/samples/text.zip
这些命令是用 PowerShell 将一个单词语料库下载到计算机中。我们创建一个新目录,可以将解压后的文件放在里面:
mkdir Downloads\text_examples
现在我们要向 PowerShell 中添加一个新函数,用来提取压缩的文件。输入下列命令:
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zipfile, [string]$outpath)
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}
定义好了这个函数,我们可以用它来解压文件。试着将下载内容解压到新文件夹中:
Unzip Downloads\text.zip Downloads\text_examples
输入 exit
就可以退出 PowerShell。提示符应该会变回 cmd 的标准提示符。输入 dir Downloads\text_examples
,你应该会看到许多下载好的语料库文本文件。我们用 findstr
在这些文件中查找:
findstr "neat" Downloads\text_examples\*.txt
你应该会看到控制台中滚动输出了许多文本。它们是包含单词 neat 的文本文件中的匹配行。
有时你想搜索特定的文件名,而不是文件中的字符串。你可以用 dir
命令加一个过滤器(filter)来做到这一点:
dir -r -filter "*.txt"
这应该会找出主文件夹下所有子文件夹中的 .txt 文件。如果你需要继续在这些文件中搜索,可以使用管道操作。|
字符可以将第一个命令的输出通过管道传递给下一个命令。比如说,我们可以用管道找到包含特定函数名的所有 Python 文件,或找到包含特定国家名称的所有 CSV 文件。我们试一下,将 findstr
的输出通过管道传递给 find
命令:
findstr /s "snake" *.txt | find i "snake" c
这段代码的作用是,首先找出包含单词 snake 的文本文件,然后利用 find
计算单词 snake 在这些文件中出现的次数。可以看出,学习更多 cmd 命令及其用法将有助于大大简化数据处理人员和开发人员的很多任务,如搜索文件、运行代码、管理工作等。关于这一话题,本附录介绍了一些内容,你可以在此基础上深入学习。
C.2.5 更多资源
想要学习如何将 cmd 用于日常编程和数据处理工作,有许多可以查找 cmd 命令的优秀在线资源(http://ss64.com/nt/)。
如果你想学习更多 PowerShell 的知识,以及如何用 PowerShell 创建强大的脚本并用于 Windows 服务器和计算机,可以阅读一些教程,如微软的 Getting Started with PowerShell 3.0 教程(https://mva.microsoft.com/en-us/training-courses/getting-started-with-powershell-30-jump-start-8276?l=r54IrOWy_2304984382)。你还可以参考 O'Reilly 出版的 Windows PowerShell Cookbook(http://shop.oreilly.com/product/0636920024132.do)开始编写你的第一个脚本。