LionKing数据科学专栏

购买普通会员高级会员可以解锁网站精华内容且享受VIP服务的优惠

想要查看更多数据科学相关的内容请关注我们的微信公众号知乎专栏

类Unix操作系统(Unix-like operating system)

介绍

类Unix操作指的是类似Unix操作系统的一大类操作系统,包括了个人电脑主流的Mac OS和服务器主流的Linux系统(如Ubuntu、Fedora、CentOS等发行版)。

个人电脑上使用类Unix系统时也可以很方便地使用图形界面(graphical user interface; GUI),但是使用服务器时基本只能使用其命令行(command-line interface; CLI)。即使是在个人电脑上,命令行的使用效率也显著高于图形界面的使用。

因此,尽管学习命令行需要花费一些时间和精力,但是在熟练掌握命令行之后,工作效率能够得到显著提升。

本文介绍最常用的一些命令行使用方法。不同的系统的命令可能略有不同,这里介绍Mac OS和Ubuntu。

操作命令行一般使用终端(terminal)应用。

路径(path)

路径可以代表对应Windows文件夹的目录(directory)或普通文件(file)。

目录可以包含0个或至少1个文件。

用户始终在某个目录下工作,称为工作目录(working directory)。

路径分为绝对路径(absolute path)和相对路径(relative path),其中绝对路径表示该路径表示一个确定的目录或文件,与工作目录无关;相对路径是相对于工作目录定义的,代表了该路径与工作目录的关系。

特殊的路径包括:

从一个路径进入下一级路径只需要加入/<目录或文件名>。

/Users/admin
├── dir1
│   ├── dir3
│   └── file1
├── dir2
└── file2
	

假设~为/Users/admin,其中包含了dir1和dir2两个目录和file2文件,dir2为空目录,dir1含有一个空目录dir3和一个文件file1。

则dir1的绝对路径为/Users/admin/dir1,dir2的绝对路径为/Users/admin/dir2,dir3的绝对路径为/Users/admin/dir1/dir3,file1的绝对路径为/Users/admin/dir1/file1。

若工作目录为/Users/admin/dir1,则..为/Users/admin,../dir2为/Users/admin/dir2,dir3为/Users/admin/dir1/dir3,file1为/Users/admin/dir1/file1。

Q:若工作目录为dir3,则dir2相对于工作目录的相对路径是什么?

权限

每个文件有自己的权限(permission),包括了用户属主(owner)、属组(group)、其它用户(other users)的读(read)、写(write)、执行(execute)三种权限。

例如可能对于某个用户建立的txt文件,属主只有读、写权限,属组和其它用户只有读权限。

那么所有人都可以阅读文件内容,但是只有属主可以修改文件。

命令

一个命令的形式为:

$ 命令名 -选项 参数
	

这里我们用"$ "$表示终端提示(prompt),命令名是命令的名称,帮助计算机寻找该命令对应的程序,一般是一个英文单词,-选项(flag)是可选(optional)的选项,可以改变命令的效果,参数(argument)是该命令需要的参数取值。以python为例:

$ python
	

表示打开python的交互式界面。

$ python main.py
	

表示使用python运行main.py程序,并在终端显示输出。

$python -i main.py
	

为交互式(interactive)选项,表示运行main.py程序并进入python的交互式界面。

有时需要在一个命令前面加上sudo使其以超级用户(superuser)即root权限运行。

若对于一个命令的使用有疑问,可以通过man命令进行查询。如man python显示了python命令的说明文档。

命令之间可以使用;或&&链接,表示第一个命令完成后执行第二个命令。

重复上一个命令可以使用!!,一般结合sudo使用。重复上一个以v开头的命令可以使用!v。

$ pwd
/Users/admin
$ !!
/Users/admin
$ ls
dir1 dir2 file2
$ !p
/Users/admin
$ chmod a+x file2
chmod: illegal option -- -
$ sudo !! # sudo执行上述命令
Password:
	

下文假设工作目录为/Users/admin,且file1包含一行"This is file 1.",file2包含一行"This is file 1."。

/Users/admin
├── dir1
│   ├── dir3
│   └── file1: This is file 1.
├── dir2
└── file2: This is file 2.
        

文件系统

命令 例子

ls

列出目标目录下的所有内容

可以选择的选项有:

  • -l,显示文件大小、访问权限等
  • -a,显示隐藏文件,隐藏文件的文件名用"."开头
  • -R,显示子目录内容
  • -d,进列出目录本身
  • -h,将文件容量以G/KB等人类易读(human readable)地显示

参数为目标目录,可以是绝对/相对目录。缺失时默认为当前目录.。

$ ls
dir1 dir2 file2
$ ls dir1
dir3 file1
$ ls -a dir1
. .. dir3 file1
$ ls -R dir1
dir3 file1

dir1/file3:
$ ls /Users/admin # 绝对路径
dir1 dir2 file2
$ ls .. # 相对路径:上一级目录
playground
$ ls -hal
total 8
drwxr-xr-x    5 admin  admin   170B Jul  8 18:27 .
drwx------+ 178 admin  admin   5.9K Jul  8 14:06 ..
drwxr-xr-x    4 admin  admin   136B Jul  8 18:27 dir1
drwxr-xr-x    2 admin  admin    68B Jul  8 18:05 dir2
-rw-r--r--    1 admin  admin    16B Jul  8 18:27 file2
		

第一列显示了文件/目录的权限,从左到右一次为:

  1. 是否为目录
  2. 属主是否有可读权限
  3. 属主是否有可写权限
  4. 属主是否有可执行权限
  5. 属组是否有可读权限
  6. 属组是否有可写权限
  7. 属组是否有可执行权限
  8. 其他人是否有可读权限
  9. 其他人是否有可写权限
  10. 其他人是否有可执行权限

cd

将工作目录改为目标目录。

参数为目标目录,可以是绝对/相对目录。

$ cd dir1 # 转移到dir1
$ ls
dir3 file1
$ ls ..
dir1 dir2 file2
$ cd ../dir2 # 转移到dir2
$ cd - # 回到上一次所在的目录,即dir1
$ ls
dir3 file1
		

pwd

打印工作目录。

$ pwd
/Users/admin
$ cd dir2
$ pwd
/Users/admin/dir2
		

touch

参数是该文件的路径,若已经存在,会改变文件的上次读取时间;否则,会建立空文件。

$ touch file2 # 改变file2的上次读取时间
$ touch file3 # 新增文件file3
$ ls
dir1 dir2 file2 file3
		

mkdir

建立目标目录。

可选选项为-p,表示若目标目录的任何一个中间目录(intermediate directory)不存在,则建立该目录。

参数为目标目录。

$ mkdir dir4 # 建立dir4
$ mkdir -p dir5/dir6 # 建立dir5,并建立dir5/dir6
		

rm

删除目标目录/文件。

可选选项为-r,表示递归地删除,用来删除文件。

参数为目标目录/文件。

使用时需小心误删重要文件!

$ rm dir2 # 不能直接删除目录
rm: dir2: is a directory
$ ls
dir1 dir2 file2
$ rm -r dir2
$ ls
dir1 file2
$ touch tmp # 建立新文件tmp
$ rm tmp # 删除tmp
$ mkdir tmp # 建立空目录tmp
$ rmdir tmp # rmdir可以删除空目录
		

cp

将原文件/目录复制到目标路径。

可选选项-r表示复制目录。

参数有两个,分别为原文件/目录,和目标路径。

$ cp file2 file3 # 将file2复制到file3
$ ls
dir1 dir2 file2 file3
$ cp dir2 dir4 # 需要使用-r选项
cp: dir2 is a directory (not copied).
$ cp -r dir2 dir4
$ ls
dir1 dir2 dir4 file2 file3
		

mv

类似cp,但是删除原目录/文件,即移动目录/文件。

不需要使用-r选项即可移动目录。

$ mv file2 file3 # 将file2重命名为file3
$ mv dir2 dir4
$ ls
dir1 dir4 file3
		

文件信息

命令 例子

cat

打印一个或多个文件内容。

参数可以为一个或多个文件名。

$ cat file2
This is file 2.
$ cat dir1/file1 file2
This is file 1.
This is file 2.
		

head

打印文件的前count行。count的默认值为10。

可选选项为-n count,表示打印前count行。

参数为一个或多个文件名。

首先新建文件tmp并且在前10行分别输入$1, 2, \ldots, 10$。

$ head -n 1 tmp
1
$ head -n 2 tmp file2
==> tmp <==
1
2

==> file2 <==
This is file 2.
		

tail

类似head,打印文件的后count行。

首先新建文件tmp并且在前10行分别输入$1, 2, \ldots, 10$。

$ tail -n 2 tmp
9
10
		

less

分屏显示文件内容。是一个很方便的快速查看文件的方式。

按Ctrl+u向上滚动、Ctrl+d向下滚动、q退出。

$ less file2 # 查看file2的内容
		

wc

统计文件的行数/单词数/字符数。

可选选项有:

  • -l,显示行数。
  • -w,显示单词数。
  • -m,显示字符数。

参数为文件。

$ wc -l file2 # 行数
1 file2
$ wc -w file2 # 单词数
4 file2
$ wc -m file2 # 字符数
16 file2
		

diff

比较两个文件的内容。

参数为第一个文件名和第二个文件名。

"< "后的内容为第一个文件多出来的行。

"> "后的内容为第二个文件多出来的行。

两个文件相同的行不会显示。

$ diff dir1/file1 file2
1c1
< This is file 1.
---
> This is file 2.
		

sort

对文件内容进行排序输出。默认排序方式为按照字典序(alphabetical order)升序排列。

可选选项有:

  • -n,当作数值进行排序,适合数据文件。
  • -r,降序排列。

建立一个tmp文件,前三行内容分别为1, 2, 10。

$ sort tmp
1
10
2
$ sort -n tmp
1
2
10
$ sort -r tmp
2
10 1
$ sort -nr tmp
10
2
1
		

grep

在文件/目录中查找模式(pattern)出现的行。

可选选项为-R表示递归地在文件/目录中查找,-l表示只显示文件名。

第一个参数为模式的字符串,可以使用正则表达式。

第二个参数为文件/目录所在的路径。

$ grep "This" *
grep: dir1: Is a directory
grep: dir2: Is a directory
file2:This is file 2.
$ grep -l "This" *
grep: dir1: Is a directory
grep: dir2: Is a directory
file2
$ grep -R "This" .
./dir1/file1:This is file 1.
./file2:This is file 2.
$ grep -R "[0-9]*" .
./dir1/file1:This is file 1.
./file2:This is file 2.
		

权限管理

命令 例子

chown

改变文件/目录的权限。

可选选项为-R表示递归地更改整个文件/目录。

第一个参数为权限改动方式,第二个参数为文件/目录的所在路径。

第一个参数可以是一个8进制的数字,也可以在u/g/o/a选择一个分别代表属主/属组/其他人/所有人、在+/-/=选择一个分别代表增加/减少/设为、在r/w/x选择一个分别代表可读/可写/可执行。

$ ls -hal file2
-rw-r--r--  1 admin  admin    16B Jul  8 19:12 file2
$ sudo chmod u+x file2 # 给属主加上可执行权限
$ sudo chmod o-r file2 # 给其他人去除可读权限
$ ls -hal file2
-rwxr-----  1 admin  admin    16B Jul  8 19:12 file2
$ sudo chmod a+rw file2 # 给所有人家上可读和可写权限
$ ls -hal file2
-rwxrw-rw-  1 admin  admin    16B Jul  8 19:12 file2
$ sudo chmod 0777 file2 # 八进制数0777对应0111111111,即所有人都有所有权限
$ ls -hal file2
-rwxrwxrwx  1 admin  admin    16B Jul  8 19:12 file2
$ sudo chmod 0644 file2 # -rw-r--r--即0110100100对应八进制数0644
-rw-r--r--  1 admin  admin    16B Jul  8 19:12 file2
		

chown/chgrp

改变文件的所有者(owner)/用户组(group)。

可选选项为-R表示递归地改变整个文件/目录。

第一个参数为新的所有者/用户组,第二个参数为文件/目录的路径。

$ ls -hal file2
-rw-r--r--  1 admin  admin    16B Jul  8 19:12 file2
$ sudo chown root file2
$ ls -hal file2
-rw-r--r--  1 root  admin    16B Jul  8 19:12 file2
$ sudo chgrp netusers file2
$ ls -hal file2
-rw-r--r--  1 root  netusers    16B Jul  8 19:12 file2
		

其它命令

命令 例子

which

命令本身是一个可执行的文件,因此也存在于文件系统的某个路径下。

which可以查找命令所在的路径。

参数为命令名。

$ which sort
/usr/bin/sort
$ which which
which: shell built-in command
		

zip

压缩文件/目录

可选选项-r表示递归地压缩文件/目录。

参数为压缩后的zip文件的路径以及一个或多个文件/目录。

$ zip a.zip file2 # 将file2压缩为a.zip
$ zip -r a.zip * # 将当前目录压缩为a.zip
		

unzip

解压zip文件。

可选选项为

  • -v,查看文件目录列表,但不解压。
  • -d,解压到中目录。
  • -n,不覆盖已有文件。
  • -o,覆盖已有文件。
$ touch tmp1 tmp2 tmp3
$ zip a.zip tmp*
$ unzip -v a.zip
Archive:  a.zip
 Length   Method    Size  Ratio   Date   Time   CRC-32    Name
--------  ------  ------- -----   ----   ----   ------    ----
       0  Stored        0   0%  07-08-18 21:59  00000000  tmp1
       0  Stored        0   0%  07-08-18 21:59  00000000  tmp2
       0  Stored        0   0%  07-08-18 21:59  00000000  tmp3
--------          -------  ---                            -------
       0                0   0%                            3 files
$ unzip a.zip
Archive:  a.zip
replace tmp1? [y]es, [n]o, [A]ll, [N]one, [r]ename: N
$ unzip -n a.zip
Archive:  a.zip
$ unzip -o a.zip
Archive:  a.zip
 extracting: tmp1
 extracting: tmp2
 extracting: tmp3
$ unzip -d tmp a.zip
Archive:  a.zip
 extracting: tmp/tmp1
 extracting: tmp/tmp2
 extracting: tmp/tmp3
		

tar

压缩/解压缩文件/目录。

可选参数较多,一般用-czvf进行压缩,用-xzvf进行解压缩。

压缩时,需要提供后缀为tar.gz的压缩文件路径和一个或多个文件/目录的路径。

解压缩时,需要提供tar.gz压缩文件路径。可选地,可以加上-C和解压到的目录。

$ touch tmp1 tmp2 tmp3
$ tar -czvf a.tar.gz tmp*
a tmp1
a tmp2
a tmp3
$ mkdir tmp
$ tar -xzvf a.tar.gz -C tmp
x tmp1
x tmp2
x tmp3
$ ls tmp
tmp1 tmp2 tmp3
		

wget

下载URL地址对应的文件。

参数为URL地址。

$ wget www.dscademy.com/index.php # 下载dscademy主页
		

ping

检测与目标机器网络是否联通。

可选参数为-c表示发送包数,默认无限次发送直到Ctrl+c终止。

$ ping -c 10 www.dscademy.com
PING dscademy.com (107.180.41.245): 56 data bytes
64 bytes from 107.180.41.245: icmp_seq=0 ttl=43 time=259.548 ms
64 bytes from 107.180.41.245: icmp_seq=1 ttl=43 time=262.591 ms
64 bytes from 107.180.41.245: icmp_seq=2 ttl=43 time=686.698 ms
64 bytes from 107.180.41.245: icmp_seq=3 ttl=43 time=259.871 ms
64 bytes from 107.180.41.245: icmp_seq=4 ttl=43 time=831.470 ms
64 bytes from 107.180.41.245: icmp_seq=5 ttl=43 time=613.915 ms
64 bytes from 107.180.41.245: icmp_seq=6 ttl=43 time=956.347 ms
64 bytes from 107.180.41.245: icmp_seq=7 ttl=43 time=258.060 ms
64 bytes from 107.180.41.245: icmp_seq=8 ttl=43 time=258.481 ms
64 bytes from 107.180.41.245: icmp_seq=9 ttl=43 time=260.027 ms

--- dscademy.com ping statistics ---
10 packets transmitted, 10 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 258.060/464.701/956.347/264.536 ms
		

shutdown/reboot

关机/重启

$ sudo shutdown -h +5 "this system will be reboot after 5 minutes" # 5分钟后关机
Shutdown at Sun Jul  8 22:26:31 2018.
shutdown: [pid 86218]
$ sudo reboot # 现在重启
		

history

查看历史命令。

$ ls
$ history | tail -n 1
930809	ls
		

open/xdg-open

在Mac/Linux中使用正确的(图形界面)应用打开一个文件/目录。

$ open dir1 # 使用Finder/nautilus打开dir1目录
$ touch a.py; open a.py # 使用Xcode/IDLE打开a.py
$ touch index.html; open index.html # 使用Chrome/Firefox打开index.html
		

多命令结合

命令行中的命令的输出除了直接打印在控制台(console)内,还可以选择打印在文件里或作为下一个命令的输入。

前者的方式是在命令的结尾加上>或>>和文件名。

例如echo "hello"的效果是输出"hello",如果接上> tmp则将删除tmp所有内容,并且写入其输出,即"hello";如果接上>>,则不删除原来内容,加上"hello"。

$ echo "hello" > tmp && cat tmp
hello
$ echo "hello" >> tmp && cat tmp
hello
hello
$echo "hello" > tmp && cat tmp
hello
	

后者称为管道(pipe)。其作用是将前面命令的输出作为后面命令的输入。

例如可以将cat的结果作为head的输入。

$ echo "1\n2\n3" > tmp && cat tmp | head -n 2 | tail -n 1
2
	

另外还可以使用脚本语言,如bash、Python、perl进行更复杂的编程完成任务,这里限于篇幅不做介绍。

安装外部软件

类Unix系统安装软件可以使用图形界面的资源中心,也可以使用更方便的命令行工具。

Mac OS可以使用homebrew软件,成功安装后使用brew install <包名>即可安装包。

下载使用Ruby:

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
	

Ubuntu可以使用apt-get命令,例如

$ sudo apt-get install python-pip
	

安装Python的包管理器pip。

编程

类Unix系统上编程非常方便,这里讲解几个Python和C++的例子。

第一个例子是一个不需要用户输入的程序。

再来看一个需要用户输入一个整数N,程序会打印N + 1的例子。

如果输入不是用户手动输入,而是来自一个文件,或者一个命令的输出,则需要用到上一节的管道(pipe)。

我们来看一个既需要用户输入又需要命令行参数的例子。

更改默认配置

终端应用启动前,会自动执行一个文件,一般来说是~/.bash_profile。

因此,如果有一些配置,希望计算机始终保持,可以在该文件里加入相应的内容。

终端在执行一个命令的时候,会在全局变量$PATH中遍历并寻找是否有可执行文件的名字和该命令名字相同,如果存在,执行该文件。

例如/usr/bin属于$PATH变量中,sort存在/usr/bin/目录下,因此终端可以找到/usr/bin/sort这个文件并执行。

加入用户新写了一个工具mysort,并且存在了~/program/目录下,希望在终端内输入mysort命令时,可以执行~/program/mysort文件。

那么可以使用export将~/programs加在$PATH中,并且存入~/.bash_profile文件。

假设用户希望将向google发送10次包的命令

ping -c 10 www.google.com
	

存成一个方便的快捷键fping,那么可以使用别名(alias)。

~/.bash_profile如下:

export PATH=$PATH:~/programs/
alias fping="ping -c 10 www.google.com"
	

那么每次开机或者登录的时候,这两个配置都会自动执行,进而可以直接使用mysort和fping两个命令。

远程登录

远程登录服务器或笔记本电脑时,使用图形界面不再方便。

此时使用本文的各种命令行工具即可完成各类任务。

本节讲解服务器的登录和文件在本地和服务器之间的转移。

登录服务器使用的标准命令是ssh,其用法如下:

ssh -p 22 root@107.180.41.245
	

可以以root身份登录IP地址为107.180.41.245,端口(port)为22的机器,需要输入对应的密码。

登陆后,就可以类似于本机打开终端一样地操作远程机器。

传输文件的命令是scp,其用法如下:

scp -P 22 ~/program/mysort root@107.180.41.245:/home/admin/program/
	

可以将本机的~/program/mysort文件上传到服务器的/home/admin/program/目录下。

更方便的一个命令是sftp,首先登录远程服务器。

sftp -P 22 root@107.180.41.245
	
sftp> lls # 本地执行ls
program
sftp> lcd program # 本地执行cd
sftp> lls
mysort
sftp> ls # 远程执行ls
program
sftp> cd program # 远程执行cd
sftp> put mysort # 将本地的mysort文件上传到远程的工作目录
sftp> get mysort # 将远程的mysort文件上传到本地的工作目录
	

为了避免重复地输入密码,可以使用如下方法跳过密码验证步骤。

$ ssh-keygen -t rsa -b 4096 # 生成RSA的公钥(public key)和私钥(private key); 无需输入文件和passphrase,直接按回车即可
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/admin/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/admin/.ssh/id_rsa.
Your public key has been saved in /Users/admin/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:??????????????????????????????????????????? admin@localhost
The key's randomart image is:
+---[RSA 4096]----+
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
|?????????????????|
+----[SHA256]-----+
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@107.180.41.245 # 将公钥上传到服务器
	

软件推荐

这里推荐一些提高办公效率的软件/工具。

更多面试问题见面试真题汇总

想要查看更多数据科学相关的内容请关注我们的微信公众号知乎专栏