2019-06-13 | UNLOCK

Linux期末复习

vi编辑器的使用

vi编辑器

1) 命令行模式

用户在用vi编辑文件时,最初进入的为一般模式。在该模式中可以通过上下移动光标进行“删除字符”或“整行删除”等操作,也可以进行“复制”、“粘贴”等操作,但无法编辑文字。

2) 插入模式

只有在该模式下,用户才能进行文字编辑输入,用户课按[ESC]键回到命令行模式

3) 底行模式

在该模式下,光标位于屏幕的底行。用户可以进行文件保存或退出操作,也可以设置编辑环境,如寻找字符串、列出行号等。

使用vi编辑器的基本流程

1) 进入vi,即在命令行下键入vi hello(文件名)。此时进入的是命令行模式,光标位于屏幕的上方。

2) 在命令行模式下键入i进入到插入模式,可以看出,在屏幕底部显示有“插入”表示插入模式,在该模式下可以输入文字信息。

3) 最后,在插入模式中,输入“Esc”,则当前模式转入命令行模式,并在底行行中输入“:wq”(存盘退出)进入底行模式。这样,就完成了一个简单的vi操作流程:命令行模式**插入模式**底行模式。由于vi在不同的模式下有不同的操作功能,因此,同学们一定要时刻注意屏幕最下方的提示,分清所在的模式。

vi的各模式功能键

1) 命令行模式常见功能键如表1所示。

表1 vi命令行模式功能键

命 令 命 令 内 容
I 切换到插入模式,此时光标当于开始输入文件处
A 切换到插入模式,并从目前光标所在位置的下一个位置开始输入文字
O 切换到插入模式,且从行首开始插入新的一行
[ctrl]+[b] 屏幕往“后”翻动一页
[ctrl]+[f] 屏幕往“前”翻动一页
[ctrl]+[u] 屏幕往“后”翻动半页
[ctrl]+[d] 屏幕往“前”翻动半页
0(数字0) 光标移到本行的开头
G 光标移动到文章的最后
nG 光标移动到第n行
$ 移动到光标所在行的“行尾”
n 光标向下移动n行
/name 在光标之后查找一个名为name的字符串
?name 在光标之前查找一个名为name的字符串
x 删除光标所在位置的一个字符
X 删除光标所在位置的“前面”一个字符
dd 删除光标所在行
ndd 从光标所在行开始向下删除n行
yy 复制光标所在行
nyy 复制光标所在行开始的向下n行
p 将缓冲区内的字符粘贴到光标所在位置(与yy搭配)
u 恢复前一个动作

2) 插入模式的功能键只有一个,也就是Esc退出到命令行模式

3) 底行模式常见功能键如表2所示

表2 vi底行模式功能键

命 令 命 令 内 容
:w 将编辑的文件保存到磁盘中
:q 退出Vi(系统对做过修改的文件会给出提示)
:q! 强制退出Vi(对修改过的文件不作保存)
:wq 存盘后退出
:w [filename] 另存一个命为filename的文件
:set nu 显示行号,设定之后,会在每一行的前面显示对应行号
:set nonu 取消行号显示

Linux命令的使用

1.编译C语言文件,并执行它

编译C语言源程序hello.c,生成可执行文件hello,命令如下:

1
gcc -o hello hello.c

运行当前目录下的可执行文件hello,执行如下命令:

1
./hello

2.打开终端快捷键

Ctrl+Alt+T

3.用户切换(su)

1) 作用

变更为其它使用者的身份,主要用于将普通用户身份转变为超级用户,而且需输入相应用户密码。

2) 格式

su [选项] [使用者]

其中的使用者为要变更的对应使用者。

3) 常见参数

主要选项参数见表1所示。

表1 su命令常用参数

选 项 参 数 含 义
-,-l,–login 为该使用者重新登录,大部分环境变量(如HOME、SHELL和USER等)和工作目录都是以该使用者(USER)为主,若没有指定USER,缺省情况是root
-m,-p 执行su时不改变环境变量
-c,–command 变更账号为USER的使用者,并执行指令(command)后再变回原来使用者

4) 使用示例

1
linux@ubuntu64-vm:~$ su -root

密码:

root@ubuntu64-vm:~#

示例通过su命令将普通用户变更为root用户,并使用选项“-”携带root环境变量。

5) 使用说明

在将普通用户变更为root用户时建议使用”-”选项,这样可以将root的环境变量和工作目录同时带入,否则在以后的使用中可能会由于环境变量的原因而出错。

在转变为root权限后,提示符变为#。

4.用户管理useradd和passwd

1) 作用

useradd:添加用户账号。

passwd:更改对应用户账号密码。

这两个命令都是root用户才能使用的命令。

2) 格式

useradd [选项] [用户名]

passwd [选项] [用户名]

其中的用户名为修改账号密码的用户,若不带用户名,缺省为更改当前使用者账号密码。

3) 常用参数

useradd主要选项参数见表2所示,passwd一般很少使用选项参数。

表2 useradd命令常用参数

选 项 参 数 含 义
-g 指定用户所属的群组
-m 自动建立用户的登入目录
-n 取消建立以用户名称为名的群组

4) 使用实例

1
root@ubuntu64-vm:~# useradd -m szpt

​ //添加用户szpt,同时自动建立szpt目录

1
root@ubuntu64-vm:~# passwd szpt

​ //设置szpt账户的登录密码

输入新的 UNIX 密码:

重新输入新的 UNIX 密码:

passwd:已成功更新密码

1
root@ubuntu64-vm:~# su -szpt

​ //切换到szpt用户

1
$ pwd

//显示当前路径

/home/szpt

$

实例中先添加了用户名为szpt的用户,接着又为该用户设置了账号密码。并从su的命令可以看出,该用户添加成功,其工作目录为“/home/szpt”。

但在进入szpt的用户后,Linux的Shell提示中并没有当前用户的提示,这是因为useradd的时候没有指定用户的shell类型,因为系统默认为/bin/sh。

1
echo $SHELL

//查看当前用户的shell类型

1
su -root

//切换到超级用户

1
chsh -s /bin/bash szpt

//改变当前用户登录默认的shell(需在root下)

1
usermod -s /bin/bash username

//或者使用此命令改变当前用户登录默认的shell

默认的shell改成/bin/bash之后正常了。

新建的用户没有sudo权限,如何修改?

1
sudo cat /etc/group

​ //在用户组中查看权限

可以看到sudo组中是没有这个用户szpt的,所以接下来就需要添加:

1
sudo usermod -G sudo -a szpt

//将用户szpt添加到sudo组里面,参数-G后面跟着组名,-a后跟着用户名

之后就可以在sudo组中看到创建的用户了

5) 使用说明

在使用添加用户时,这两个命令是一起使用的,useradd必须用root的权限。

useradd指令所建立的账号,是保存在“/etc/passwd”文本文件中,文件中每一行包含一个账号信息

缺省情况下,useradd所做的初始化操作包括在“/home”目录下为对应账号建立一个同名的主目录,并且还为该用户单独建立一个同名的组。

adduser只是useradd的符号链接(关于符号链接的概念在本节后面会有介绍),两者是相同的。

passwd还可用于普通用户修改账号密码,Linux并不采用类似windows的密码回显(显示为*号),所以输入的这些字符用户是看不见的。

5.系统管理命令ps和kill

1) 作用

ps:显示当前系统中由该用户运行的进程列表。

kill:输出特定的信号给指定PID(进程号)的进程,并根据该信号而完成指定的行为。其中可能的信号有进程挂起、进程等待、进程终止等。

2) 格式

ps:ps [选项]

kill:kill [选项] 进程号(PID)

kill命令中的进程号为信号输出的指定进程的进程号,当选项是缺省时为输出终止信号给该进程。

3) 常用参数

ps主要选项参数见表3所示,kill主要选项参数见表4所示。

表3 ps命令常用参数列表

选 项 参 数 含 义
-ef 查看所有进程及其PID(进程号)、系统时间、命令详细目录、执行者等
-aux 除可显示-ef所有内容外,还可显示CPU及内存占用率、进程状态
-w 显示加宽并且可以显示较多的信息

表4 kill命令常用参数列表

选 项 参 数 含 义
-s 根据指定信号发送给进程
-p 打印出进程号(PID),但并不送出信号
-l 列出所有可用的信号名称

4) 使用实例

1
root@ubuntu64-vm:~# ps –ef

查看所有进程,然后再在桌面上打开浏览器firefox,把打开的浏览器放在一边,然后用ps命令找出该进程的PID。

1
root@ubuntu64-vm:~# ps -ef|grep firefox

linux 14150 1 19 20:33 ? 00:00:29 /usr/lib/firefox/firefox

root 14628 12713 0 20:36 pts/4 00:00:00 grep –color=auto firefox

1
root@ubuntu64-vm:~# kill 14150

用kill命令终止进程号为14150的firefox进程,这时刚才打开的浏览器已直接关闭,再用ps命令查看时已经没有该进程号的进程。

5) 使用说明

ps在使用中通常可以与其他一些命令结合起来使用,主要作用是提高效率。

ps选项中的参数w可以写多次,通常最多写3次,它的含义表示加宽3次,这足以显示很长的命令行了。例如:ps –auxwww。

6.文件目录相关命令

1.cd(改变路径)

1) 作用

改变工作目录。

2) 格式

cd [路径]

其中的路径为要改变的工作目录,可为相对路径或绝对路径。

3) 使用实例

1
root@ubuntu64-vm:~# cd /home/linux

//目前处于超级用户root下,变更工作目录到Linux目录下

1
root@ubuntu64-vm:/home/linux# pwd

​ //显示当前路径

​ /home/linux

4) 使用说明

该命令将当前目录改变至指定路径的目录。若没有指定路径,则回到用户的主目录。为了改变到指定目录,用户必须拥有对指定目录的执行和读权限。

该命令可以使用通配符

可使用

1
cd -

//可以回到前次工作目录

./ ”代表当前目录

../ ”代表上级目录

1
cd ~

//回到当前用户的主目录。

2.ls(查看当前目录列表)

1) 作用

列出目录的内容。

2) 格式:ls [选项] [文件]

其中文件选项为指定查看指定文件的相关内容,若未指定文件,默认查看当前目录下的所有文件。

3) 常用参数

ls主要选项参数见表6所示。

表6 ls命令常用参数列表

选 项 参 数 含 义
-1,–format=single-column 一行输出一个文件(单列输出)
-a,-all 列出目录中所有文件,包括以“.”开头的文件
-d 将目录名和其他文件一样列出,而不是列出目录的内容
-l,–format=long, –format=verbose 除每个文件名外,增加显示文件类型、权限、硬链接数、所有者名、组名、大小(**Byte**)及时间信息(如未指明是其他时间即指修改时间)
-f 不排序目录内容,按它们在磁盘上存储的顺序列出

4) 使用实例

1
root@ubuntu64-vm:/home/linux# ls –l

//查看当前目录下所有文件,并通过选项“-l”显示出详细信息

总用量 52 //当前目录下文件和目录所占用的文件块的数量为52,一个文件块的大小为4K

-rw-r–r– 1 linux linux 8445 8月 20 2013 examples.desktop

-rw-rw-r– 1 linux linux 76 11月 8 2013 README

-rw-rw-r– 1 linux linux 0 7月 1 2016 support@farsight.com.cn

drwxrwxr-x 2 linux linux 4096 11月 4 2014 workdir

drwxr-xr-x 2 linux linux 4096 8月 20 2013 公共的

drwxr-xr-x 2 linux linux 4096 8月 20 2013 模板

drwxr-xr-x 2 linux linux 4096 8月 20 2013 视频

drwxr-xr-x 2 linux linux 4096 8月 20 2013 图片

drwxr-xr-x 2 linux linux 4096 8月 20 2013 文档

drwxr-xr-x 2 linux linux 4096 8月 20 2013 下载

drwxr-xr-x 2 linux linux 4096 8月 20 2013 音乐

drwxr-xr-x 2 linux linux 4096 8月 20 2013 桌面

显示格式说明如下:

文件类型与权限 链接数 文件拥有者 所属的用户组 文件大小 修改的时间 文件或目录名字

(d表示类型是目录,r可读,w可写,x可执行,-不可读/写…)

5) 使用说明

在ls的常用参数中,-l(长文件名显示格式)的选项是最为常用的。可以详细显示出各种信息。

若想显示出所有“.”开头的文件(“.”开头的为隐藏文件),可以使用-a,这在嵌入式的开发中很常用。

6) Linux文件颜色的含义:

蓝色文件:目录

白色文件:一般性文件,如文本文件,配置文件,源码文件等

浅蓝色文件:链接文件,主要是使用ln命令建立的文件

绿色文件:可执行文件,可执行的程序

红色文件:压缩文件或者包文件

红色闪烁:表示链接的文件有问题

黄色文件:表示设备文件

灰色文件:表示其他文件

3.mkdir(创建文件夹)

1) 作用

创建一个目录。

2) 格式

mkdir [选项] 路径

3) 常用参数

mkdir主要选项参数如表7所示。

表7 mkdir命令常用参数列表

选 项 参 数 含 义
-m 对新建目录设置存取权限,也可以用chmod命令(后面说明)设置
-p 可以是一个路径名称。此时若此路径中的某些目录尚不存在,在加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多个目录

4) 使用实例

1
linux@ubuntu64-vm:~$ mkdir -p **./hello/my

//自动建立好那些尚不存在的目录**

1
linux@ubuntu64-vm:~$ cd **./hello/my

//**切换到指定路径

1
linux@ubuntu64-vm:~/hello/my$ **pwd

//**显示当前路径

/home/linux/hello/my

该实例使用选项“-p”一次创建了./hello/my多级目录。

1
linux@ubuntu64-vm:~$ mkdir -m 777 **./why**

//权限代码777代表三级用户(所属用户、所属用户组、其他用户)的权限为:rwxrwxrwx

1
linux@ubuntu64-vm:~$ ls -l

总用量 56

-rw-r–r– 1 linux linux 8445 8月 20 2013 examples.desktop

-rw-rw-r– 1 linux linux 76 11月 8 2013 README

-rw-rw-r– 1 linux linux 0 7月 1 2016 support@farsight.com.cn

drwxrwxrwx 2 linux linux 4096 3月 27 14:22 why //d表示是目录,-表示是文件

该实例使用选项“-m”创建了相应权限的目录。对于“777”的权限在本节后面会有详细的说明。

5) 使用说明

该命令要求创建目录的用户在创建路径的上级目录中具有写权限,并且路径名不能是当前目录中已有的目录或文件名称。

4.cat(查看文件信息)

1) 作用

连接显示指定的一个和多个文件的有关信息。

2) 格式

cat [选项]文件1文件2…

其中的文件1、文件2为要显示的多个文件。

3) 常用参数

cat命令的常用参数如表8所示。

表8 cat命令常用参数列表

选 项 参 数 含 义
-n 由第一行开始对所有输出的行数编号
-b 和-n相似,只不过对于空白行不编号

4) 使用实例

1
linux@ubuntu64-vm:~$ **cat** -n **./workdir/test

​ 1

​ 2 this is a test file!

​ 3

在该实例中,指定对test进行输出,并指定行号。

5.cp、mv和rm

1) 作用

① cp:将给出的文件或目录复制到另一文件或目录中。

② mv:为文件或目录改名或文件由一个目录移入另一个目录中。

③ rm:删除一个目录中的一个或多个文件或目录。

2) 格式

① cp:cp [选项] 源文件或目录 目标文件或目录。

② mv:mv [选项] 源文件或目录 目标文件目录

③ rm:rm [选项] 文件目录

3) 常用参数

① cp主要选项参数见表9所示。

表9 cp命令常用参数列表

选 项 参 数 含 义
-a 保留链接、文件属性,并复制其子目录,其作用等于dpr选项的组合
-d 拷贝时保留链接
-f 删除已经存在的目标文件而不提示
-i 在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,而且是交互式拷贝
-p 此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中
-r 若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件必须为一个目录名

② mv主要选项参数如表10所示。

表10 mv命令常用参数列表

选 项 参 数 含 义
-i 若mv操作将导致对已存在的目标文件的覆盖,此时系统询问是否重写,并要求用户回答y或n,这样可以避免误覆盖文件
-f 禁止交互操作。在mv操作要覆盖某已有的目标文件时不给任何指示,在指定此选项后,i选项将不再起作用

③ rm主要选项参数如表11所示。

表11 rm命令常用参数列表

选 项 参 数 含 义
-i 进行交互式删除 (每一步都有提示:是否确认删除)
-f 忽略不存在的文件,但从不给出提示
-r 指示rm将参数中列出的全部目录和子目录均递归地删除

4) 使用实例

cp(复制)

1
linux@ubuntu64-vm:~$ cp -a ./hello/my ./

//将“/hello/my”目录下的所有文件复制到当前目录下

//而此时在原先目录下还有原有的文件。

1
linux@ubuntu64-vm:~$ ls

mv(移动、重命名)

1
linux@ubuntu64-vm:~$ **mv** hello why

//将目录hello移至why目录下

1
linux@ubuntu64-vm:~$ ls

//可以看到当前目录下已经没有hello目录

1
linux@ubuntu64-vm:~$ ls ./why

//hello目录已经被移至why目录下了

hello

该实例中把“hello”目录下的所有文件移至目录why下,则原目录下文件被自动删除

rm(删除)

1
linux@ubuntu64-vm:~$ rm **-ir** **./why

//全部目录和子目录均递归地删除,每一步都有提示信息,确认是否删除(交互式)

rm:是否进入目录”./why”? y

rm:是否进入目录”./why/hello”? y

rm:是否删除目录 “./why/hello/my”? y

rm:是否删除目录 “./why/hello”? y

rm:是否删除目录 “./why”? y

5) 使用说明

① cp:该命令把指定的源文件复制到目标文件或把多个源文件复制到目标目录中。

② mv:

该命令根据命令中第二个参数类型的不同(是目标文件还是目标目录)来判断是重命名还是移动文件,当第二个参数类型是文件时,mv命令完成文件重命名,此时,它将所给的源文件或目录重命名为给定的目标文件名;

当第二个参数是已存在的目录名称时,mv命令将各参数指定的源文件均移至目标目录中;

在跨文件系统移动文件时,mv先复制,再将原有文件删除,而链至该文件的链接也将丢失。

③ rm:

如果没有使用-r选项,则rm不会删除目录;

使用该命令时一旦文件被删除,它是不能被恢复的,所以最好使用-i参数(则有交互提示信息)。

6.chown(修改文件的所有者)和chgrp(修改文件所属的组)

1) 作用

① chown:修改文件的所有者。(改变文件所属的用户)

② chgrp:改变文件的所有组。(改变文件所属的组)

2) 格式

① chown:chown [选项].文件所属用户 文件

其中的文件所属用户名为修改后的文件所属用户

② chgrp:chgrp [选项].文件所属组 文件

其中的文件所属组为改变文件所属组

3) 常用参数

chown和chgrp的常用参数意义相同,其主要选项参数如表12所示。

表12 chown和chgrp命令常用参数列表

选 项 参 数 含 义
-c,-changes 详尽地描述每个file实际改变了哪些所有权
-f,–silent,–quiet 不打印文件所有权就不能修改的报错信息

4) 使用实例

在当前的系统中目录”workdir”下的一个文件的所有者原先是这样的。

1
linux@ubuntu64-vm:~$ cd workdir
1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rw-r–r– 1 linux linux 23 8月 20 2013 test

可以看出,这是一个文件,它的文件拥有者是linux,具有可读写的权限,它所属的用户组是linux,具有可读的权限,但没有可写的权限,同样,系统其他用户对其也只有可读的权限。

首先使用chown将文件所有者改为root(超级用户)。

1
linux@ubuntu64-vm:~/workdir$ sudo chown root test
1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rw-r–r– 1 root linux 23 8月 20 2013 test

因为linux用户没有修改文件属性的权限,所以要加上sudo命令。

可以看出,此时,该文件拥有者变为了root,它所属文件用户组不变。

接着使用chgrp将文件所属组变为root。

1
linux@ubuntu64-vm:~/workdir$ sudo chgrp root test
1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rw-r–r– 1 root root 23 8月 20 2013 test

5) 使用说明

使用chown和chgrp必须拥有root权限。

7.chmod(修改文件的访问权限)

1) 作用

改变文件的访问权限

2) 格式

chmod可使用符号标记进行更改和八进制数指定更改两种方式,因此它的格式也有两种不同的形式。

① 符号标记:chmod [选项].符号权限[符号权限].文件

其中的符号权限可以指定为多个,也就是说,可以指定多个用户级别的权限,但它们中间要用逗号分开表示,若没有显示指出则表示不作更改。

② 八进制数:chmod [选项] 八进制权限 文件

其中的八进制权限是指要更改后的文件权限。

3) 常用参数

chmod主要常用参数如表13所示。

表13 chmod命令常用参数列表

选 项 参 数 含 义
-c 若该文件权限确实已经更改,才显示其更改动作
-f 若该文件权限无法被更改也不要显示错误信息
-v 显示权限变更的详细资料

4) 使用实例

chmod涉及文件的访问权限,在此对相关的概念进行简单的回顾。

文件的访问权限可表示成:- rwx rwx rwx

在此设有三种不同的访问权限:读(r)、写(w)和运行(x)。

三个不同的用户级别:文件拥有者u)、所属的用户组g)和系统里的其他用户o)。在此,可增加一个用户级别a(all)来表示所有这三个不同的用户级别。

① 对于第一种符号连接方式的chmod命令中,用加号“+”代表增加权限,用减号“删除权限,等于号“=”设置权限。

例如当前linux用户目录”workdir”下有文件test,其权限如下所示。

1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rw-r–r– 1 root root 23 8月 20 2013 test

修改其权限为:

1
linux@ubuntu64-vm:~/workdir$ chmod ugo+x test
1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rwxr-xr-x 1 root root 23 8月 20 2013 test

可见,在执行了chmod之后,所有用户都有了可执行的权限。

② 对于第二种八进制数指定的方式,将文件权限字符代表的有效位设为“1”,即“rw-”、“rw-”和“r–”的八进制表示为“110”、“110”、“100”,把这个2进制串转换成对应的8进制数就是6、6、4,也就是说该文件的权限为664(三位八进制数)。这样对于转化后8进制数、2进制及对应权限的关系如表14所示。

表14转化后8进制数、2进制及对应权限的关系

转换后8进制数 2进制 对 应 权 限 转换后8进制数 2进制 对 应 权 限
0 000 没有任何权限 1 001 只能执行
2 010 只写 3 011 只写和执行
4 100 只读 5 101 只读和执行
6 110 读和写 7 111 读,写和执行

同上例,进一步修改test文件权限为对所有用户均为可读、可写及可执行。

1
linux@ubuntu64-vm:~/workdir$ chmod 777 test
1
linux@ubuntu64-vm:~/workdir$ ls -l

总用量 4

-rwxrwxrwx 1 root root 23 8月 20 2013 test

可见,在执行了chmod 777之后,该文件的拥有者权限、文件组权限和其他用户权限都做了相应修改。

8.grep(再文件中搜索特点内容)

1) 作用

在指定文件中搜索特定的内容,并将含有这些内容的行标准输出。

2) 格式

grep [选项] 格式 [文件及路径]

其中的格式是指要搜索的内容格式,若缺省“文件及路径”则默认表示在当前目录下搜索。

3) 常用参数

grep主要选项参数如表15所示。

表15 grep命令常用参数列表

选 项 参 数 含 义
-c 只输出匹配行的计数
-h 查询多文件时不显示文件名
-i 不区分大小写(只适用于单字符)
-l 查询多文件时只输出包含匹配字符的文件名
-n 显示匹配行及行号
-s 不显示不存在或无匹配文本的错误信息
-c 只输出匹配行的计数
-v 显示不包含匹配文本的所有行

4) 使用实例

1
linux@ubuntu64-vm:~$ grep -r "hello" /

该例中,“hello”是要搜索的内容,“ -r”是指定查询目录,整个命令表示搜索根目录下的所有文件。

1
linux@ubuntu64-vm:~$ grep -r "hello" ./

该例中,“hello”是要搜索的内容,“ -r”是指定查询目录,命令表示搜索当前目录下的所有文件。

1
linux@ubuntu64-vm:~$ grep -r -s "hello" ./

该例中,“hello”是要搜索的内容,搜索当前目录下的所有文件,且不显示不存在或无匹配文本的错误信息。

1
linux@ubuntu64-vm:~$ grep -rsnh "hello" ./
1
linux@ubuntu64-vm:~$ grep "hello" ./hello.c

​ //在当前目录下的hello.c文件中查找字符串“hello”

5) 使用说明

在缺省情况下,“grep”只搜索当前目录。如果此目录下有许多子目录,

“grep”会以如下形式列出:“grep:sound:Is a directory”这会使“grep”的输出难于阅读。

但有两种解决的方法:

② 明确要求搜索子目录:grep -r**(**正如上例中所示);

忽略子目录:grep -d skip。

当预料到有许多输出,可以通过管道将其转到“less”(分页器)上阅读:如grep -r “h” ./ |less分页阅读。(less 是分页阅读文件内容的命令,按pageup、pagedown键…)

6) grep特殊用法:

grep pattern1|pattern2 files:显示匹配pattern1或pattern2的行;

grep pattern1 files|grep pattern2:显示既匹配pattern1又匹配pattern2的行;

9.find(搜索文件)

1) 作用

在指定目录中搜索文件,它的使用权限是所有用户。

2) 格式

find [路径][选项][描述]

其中的路径为文件搜索路径,系统开始沿着此目录树向下查找文件。它是一个路径列表,相互用空格分离。若缺省路径,那么默认为当前目录。

其中的描述是匹配表达式,是find命令接受的表达式。

3) 常用参数

选项的主要参数如表16所示。

表16 find选项常用参数列表

选 项 参 数 含 义
-depth 使用深度级别的查找过程方式,在某层指定目录中优先查找文件内容
-mount 不在其他文件系统(如Msdos、Vfat等)的目录和文件中查找
-name 支持通配符*****?
-user 用户名:搜索文件属主为用户名(ID或名称)的文件
-print 输出搜索结果,并且打印

4) 使用实例

1
linux@ubuntu64-vm:~$ find ./tes*.sh
1
linux@ubuntu64-vm:~$ find ./test?.sh
1
linux@ubuntu64-vm:~$ find ./ -name tes\*

​ //使用了-name*的选项支持通配符?和

//(如果报错的话,在”前加一个转义符”。)

pwd

./workdir/test

1
linux@ubuntu64-vm:~$ find ./ test

​ //**在当前目录下查找文件test

5) 使用说明

若使用目录路径为“/”,通常需要查找较多的时间,可以指定更为确切的路径以减少查找时间。

find命令可以使用混合查找的方法,

例如,想在/etc目录中查找大于500000字节,并且在24**小时内**修改的某个文件,

则可以使用-and(与)把两个查找参数链接起来组合成一个混合的查找方式,

如 “ find /etc -size +500000c -and -mtime +1 ”。(此处+1表示1个24小时)

10.Locate(查找文件)

1) 作用

用于查找文件

其方法是先建立一个包括系统内所有文件名称及路径的数据库,之后当寻找时就只需查询这个数据库,而不必实际深入档案系统之中了。因此其速度比find快很多。

2) 格式

locate [选项]

3) locate主要选项参数如表17所示。

表17 locate命令常用参数列表

选 项 参 数 含 义
-u 从根目录开始建立数据库
-U 指定开始的位置建立数据库
-f 将特定的文件系统排除在数据库外,例如proc文件系统中的文件
-r 使用正则运算式做寻找的条件
-o 指定数据库存的名称

4) 使用实例

1
linux@ubuntu64-vm:~$ locate ./ hell?.c
1
linux@ubuntu64-vm:~$ sudo updatedb

​ //在当前目录下建立了一个数据库

1
linux@ubuntu64-vm:~$ locate -r test

//进行正则匹配查找, 将找出所有文件名中包含test的文件

locate的运行速度非常快。

5) 使用说明

locate命令所查询的数据库由updatedb程序来更新的,

而updatedb是由cron daemon周期性建立的,但若所找到的档案是最近才建立或刚更名的,

可能会找不到,因为updatedb默认每天运行一次,

用户可以由修改crontab(etc/crontab)来更新周期值。

11.ln

1) 作用

某一个文件另外一个位置建立一个链接(分为硬链接和软链接即符号链接)

当需要在不同的目录用到相同的文件时,Linux允许用户不用在每一个需要的目录下都存放一个相同的文件,而只需将其他目录下文件用ln命令链接即可,这样就不必重复地占用磁盘空间。

2) 格式

ln [选项] 目标 目录

3) 常用参数

-s建立符号链接(即软链接)。

4) 使用实例

硬链接:(相当于同步的两个文件)

1
linux@ubuntu64-vm:~$ ln ex0.c el
1
linux@ubuntu64-vm:~$ ls -l eln ex0.c

-rwxrwxr-x 2 linux linux 9053 3** 21 12:34 eln**

-rwxrwxr-x 2 linux linux 9053 3** 21 12:34 ex0.c**

软链接:(相当于一个快捷方式或指针的作用)

1
linux@ubuntu64-vm:~$ ln -s ex0.c eln1
1
linux@ubuntu64-vm:~$ ls -l eln1 ex0.c

lrwxrwxrwx 1 linux linux 5 3月 21 13:50 eln1 -> ex0.c

-rwxrwxr-x 2 linux linux 9053 3月 21 12:34 ex0.c

1
linux@ubuntu64-vm:~$ ln -s ./workdir/test ./my

//为文件**test在现目录下建立符号链接my**(软链接)

(相当于快捷方式)

1
linux@ubuntu64-vm:~$ ls -l my

总用量 0

lrwxrwxrwx 1 linux linux 14 3月 27 16:16 my -> ./workdir/test

该实例建立了目录workdir下的test文件与当前目录下的my文件之间的符号连接,

在”ls -l”命令执行后,显示my文件属性中的第一位为“l”,表示符号链接,同时还显示了链接的源文件

5) 使用说明

ln命令会保持每一处链接文件的同步性,不论改动了哪一处,其他的文件都会发生相同的变化。

In的链接有软链接和硬链接两种:

l 软链接就是上面所说的ln -s \ **,它只会在用户选定的位置上生成一个文件的镜像,不会重复占用磁盘空间,平时使用较多的都是软链接**;

l 硬链接不带参数ln \ **,它会在用户选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步**变化。

7.压缩打包相关命令

1.gizp (压缩)

1) 作用

对文件进行压缩和解压缩,而且gzip根据文件类型可自动识别压缩解压

2) 格式

gzip [选项] 压缩(解压缩)的文件名

3) 常见参数

gzip主要选项参数如表18所示。

表18 gzip命令常见参数列表

选 项 参 数 含 义
-c 将输出信息写到标准输出上,并保留原有文件
-d 将压缩文件解压
-l 对每个压缩文件,显示下列字段:压缩文件的大小、未压缩文件的大小、压缩比、未压缩文件的名字
-r 查找指定目录并压缩或解压缩其中的所有文件 (将文件逐个压缩,不能压缩目录)
-t 测试,检查压缩文件是否完整
-v 对每一个压缩和解压的文件,显示文件名和压缩比

4) 使用实例

1
linux@ubuntu64-vm:~$ gzip n1.txt

​ //压缩

1
linux@ubuntu64-vm:~$ gzip -d n1.txt.gz

​ //解压

1
linux@ubuntu64-vm:~$ cd workdir
1
linux@ubuntu64-vm:~/workdir$ gzip test

//将当前目录下的“test”文件进行压缩

1
linux@ubuntu64-vm:~/workdir$ ls

test.gz

1
linux@ubuntu64-vm:~/workdir$ gzip -l test

​ //将当前目录下的“test”文件进行压缩,列出了压缩比

​ compressed uncompressed ratio uncompressed_name

​ 46 23 34.8% test

5) 使用说明

使用gzip压缩只能压缩单个文件,而不能压缩目录,

其选项“-r”是将该目录下的所有文件逐个进行压缩,而不是压缩成一个文件

2.tar(解压)

1) 作用

文件目录进行打包或解包。(注意! 不是压缩和解压缩)

在此需要对打包压缩这两个概念进行区分。

打包是指将一些文件或目录变成一个总的文件

压缩则是将一个大的文件通过一些压缩算法变成一个小文件

为什么要区分这两个概念呢?

这是由于在Linux中的很多压缩程序(如前面介绍的gzip)只能针对一个文件进行压缩,这样当想要压缩较多文件时,就要借助它的工具将这些文件先打成一个包,然后用原来的压缩程序进行压缩

2) 格式

tar [选项] [打包后文件名] 文件目录列表

tar可自动根据文件名识别打包解包动作,

其中打包后文件名为用户自定义的打包后文件名称,

文件目录列表可以是要进行打包备份的文件目录列表,也可以是进行解包的文件目录列表。

3) 常见参数

tar常见选项参数如表19所示。

表19 tar命令常见参数列表

选 项 参 数 含 义
-c 建立新的打包文件
-C 解压到指定目录中
-r 向打包文件末尾追加文件
-x 从打包文件中解出文件
-o 将文件解开到标准输出
-v 处理过程中输出相关信息
-f 指定文件名,该参数需要放在诸参数的最后
-z 调用gzip来压缩打包文件,与-x联用时调用gzip完成解压缩
-j 调用bzip2来压缩打包文件,与-x联用时调用bzip2完成解压缩
-Z 调用compress来压缩打包文件,与-x联用时调用compress完成解压缩

4) 使用实例

返回到linux的用户目录

1
linux@ubuntu64-vm:~$ tar -cvf szpt.tar **./**

​ //将当前目录(./)下的文件打包**到**szpt.tar中

​ //选项“-v”在屏幕上输出了打包的具体过程

1
linux@ubuntu64-vm:~$ ls -l szpt.tar

-rw-rw-r– 1 linux linux 35942400 3月 27 16:24 szpt.tar

1
linux@ubuntu64-vm:~$ gzip szpt.tar

​ //将szpt.tar**文件进行压缩到当前目录,生成szpt.tar.gz**

1
linux@ubuntu64-vm:~$ ls -l szpt.tar.gz

​ //查看压缩后的文件的大小,与之前的比较

1
linux@ubuntu64-vm:~$ gzip -d szpt.tar.gz

//将szpt.tar.gz解压缩到当前目录,又生成szpt.tar

1
linux@ubuntu64-vm:~$ ls

//查看解压缩后的文件

5) 使用说明

tar命令除了用于常规的打包之外,使用更为频繁的是用选项“-z”或“-j”调用gzip或bzip2(Linux中另一种解压工具)完成对各种不同文件的解压

表20对Linux中常见类型的文件解压命令做一总结。

表20 Linux常见类型的文件解压命令一览表

文 件 后 缀 解 压 命 令 示 例
.a tar xv tar xv hello.a
.z Uncompress uncompress hello.Z
.gz Gunzip gunzip hello.gz
.tar.Z tar xvZf tar xvZf hello.tar.Z
.tar.gz/.tgz tar xvzf tar xvzf hello.tar.gz
tar.bz2 tar jxvf tar jxvf hello.tar.bz2
.rpm 安装:rpm -i 安装:rpm -i hello.rpm
解压:rpm2cpio 解压:rpm2cpio hello.rpm
.deb(Debain中的文件格式) 安装:dpkg -i 安装:dpkg -i hello.deb
解压:dpkg-deb –fsys-tarfile 解压:dpkg-deb –fsys-tarhello hello.deb
.zip Unzip unzip hello.zip

使用tar命令同时完成对当前目录打包压缩

1
linux@ubuntu64-vm:~$ tar -cvzf szpt1.tar.gz ./

//对当前目录**打包压缩为**szpt1.tar.gz

//参数-z表示打包后调用gzip来压缩

1
linux@ubuntu64-vm:~$ cp szpt1.tar.gz **/****workdir

//**将szpt1.tar.gz拷贝到workdir目录下

1
linux@ubuntu64-vm:~$ cd /workdir

​ //切换到workdir目录下

1
linux@ubuntu64-vm:~/workdir$ tar -xvzf szpt1.tar.gz

//解压文件到当前目录,-z表示使用gzip,-x**表示解压**

如果要用tar命令解压文件到指定目录下,可以加一个参数-C,后面指定的目录必须存在。

1
linux@ubuntu64-vm:~/workdir$ mkdir subdir
1
linux@ubuntu64-vm:~/workdir$ tar -xvzf szpt1.tar.gz –C subdir

//注意,subdir**必须先建好才行**

//解压文件到subdir目录,-z表示使用gzip,-x**表示解压,-C表示**解压文件到后面的指定目录下

8.网络相关命令

1. ifconfig(网络配置)

1) 作用

用于查看和配置网络接口的地址和参数,包括IP地址、网络掩码、广播地址,它的使用权限是超级用户

2) 格式

ifconfig有两种使用格式,分别用于查看和更改网络接口。

ifconfig [选项] [网络接口]:用来查看当前系统的网络配置情况

ifconfig 网络接口 [选项] 地址:用来配置指定接口(如eth0,eth1)的IP地址、网络掩码、广播地址等。

3) 常见参数

ifconfig第二种格式常见选项参数如表21所示。

表21 ifconfig命令选项常见参数列表

选 项 参 数 含 义
-interface 指定的网络接口名,如eth0和eth1
up 激活指定的网络接口卡
down 关闭指定的网络接口
broadcast address 设置接口的广播地址
point to point 启用点对点方式
address 设置指定接口设备的IP地址
netmask address 设置接口的子网掩码

4) 使用实例

首先,使用ifconfig的第一种格式来查看网口配置情况。如果不识别命令,可加上sudo命令来执行。

1
linux@ubuntu64-vm:~$ sudo ifconfig

[sudo] password for linux:

eth0 Link encap:以太网 硬件地址 00:0c:29:9b:fc:df

​ inet 地址:192.168.100.192 广播:192.168.100.255 掩码:255.255.255.0

​ inet6 地址: fe80::20c:29ff:fe9b:fcdf/64 Scope:Link

​ UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1

​ 接收数据包:6843 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:2247 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:1000

​ 接收字节:447944 (447.9 KB) 发送字节:104234 (104.2 KB)

lo Link encap:本地环回

​ inet 地址:127.0.0.1 掩码:255.0.0.0

​ inet6 地址: ::1/128 Scope:Host

​ UP LOOPBACK RUNNING MTU:16436 跃点数:1

​ 接收数据包:1455 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:1455 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:0

​ 接收字节:137212 (137.2 KB) 发送字节:137212 (137.2 KB)

可以看出,使用ifconfig的显示结果中详细列出了所有活跃接口的IP**地址、硬件地址、广播地址、子网掩码、回环地址等。**

1
linux@ubuntu64-vm:~$ sudo ifconfig eth0

eth0 Link encap:以太网 硬件地址 00:0c:29:9b:fc:df

​ inet 地址:192.168.100.192 广播:192.168.100.255 掩码:255.255.255.0

​ inet6 地址: fe80::20c:29ff:fe9b:fcdf/64 Scope:Link

​ UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1

​ 接收数据包:6848 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:2257 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:1000

​ 接收字节:448244 (448.2 KB) 发送字节:104666 (104.6 KB)

在此例中,通过指定接口显示出对应接口的详细信息。另外,用户还可以通过指定参数“-a”来查看所有接口(包括非活跃接口)的信息。

接下来的示例指出了如何使用ifconfig的第二种格式来改变指定接口的网络参数配置。

③ linux@ubuntu64-vm:~$ sudo ifconfig eth0 down //**暂停网络接口eth0工作**

④ linux@ubuntu64-vm:~$ sudo ifconfig

lo Link encap:本地环回

​ inet 地址:127.0.0.1 掩码:255.0.0.0

​ inet6 地址: ::1/128 Scope:Host

​ UP LOOPBACK RUNNING MTU:16436 跃点数:1

​ 接收数据包:1473 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:1473 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:0

​ 接收字节:138940 (138.9 KB) 发送字节:138940 (138.9 KB)

在此例中,通过将指定接口的状态设置为DOWN,暂时暂停该接口的工作。

1
linux@ubuntu64-vm:~$ sudo ifconfig eth0 210.25.132.142 netmask 255.255.255.0

//****ifconfig改变网络接口eth0的IP**地址、子网掩码**

1
linux@ubuntu64-vm:~$ sudo ifconfig

eth0 Link encap:以太网 硬件地址 00:0c:29:9b:fc:df

​ inet 地址:210.25.132.142 广播:210.25.132.255 掩码:255.255.255.0

​ inet6 地址: fe80::20c:29ff:fe9b:fcdf/64 Scope:Link

​ UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1

​ 接收数据包:6860 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:2311 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:1000

​ 接收字节:448964 (448.9 KB) 发送字节:112565 (112.5 KB)

lo Link encap:本地环回

​ inet 地址:127.0.0.1 掩码:255.0.0.0

​ inet6 地址: ::1/128 Scope:Host

​ UP LOOPBACK RUNNING MTU:16436 跃点数:1

​ 接收数据包:1473 错误:0 丢弃:0 过载:0 帧数:0

​ 发送数据包:1473 错误:0 丢弃:0 过载:0 载波:0

​ 碰撞:0 发送队列长度:0

​ 接收字节:138940 (138.9 KB) 发送字节:138940 (138.9 KB)

5) 使用说明

用ifconfig命令配置的网络设备参数不需重启就可生效,但在机器重新启动以后将会失效

2. traceroute

1) 作用

为了判断外网的工作情况,可以使用另一个非常有用的命令traceroute,以确定到远方主机的路由

也就是数据包发送到远方主机需要经过哪些路由器

有时候ping某个远方主机不通是因为某个路由器引起的,则可以通过该命令发现故障。

2) 格式

traceroute IP**地址(或域名)**

3) 注意,该命令不是缺省安装的,需要下载软件包来提供支持。

3.netsta

1) 作用

为了快速检查网络接口的状态信息,可以使用该命令

2) 格式

netstat -i

netstat –a -n也可以显示主机的路由表,其作用相当于route -n (显示内核IP路由表)

netstat -t 只显示所有的激活的TCP连接

Shell编程

1) 编写Shell脚本:

试编写脚本test1.sh,内容为:

1
2
3
4
5
#!/bin/bash            #置于第一行,表示此文件中的shell命令是用的bin下的bash解释器解释的

echo "hello,world"

#!/bin/bash #非第一行的#号起注释的作用

其中第一行#!/bin/bash指定shell,而第三行就是注释

运行方式:执行命令:

1
bash test1.sh

​ (用bash命令)

或者:先将文件属性改为可执行:

1
chmod +x test1.sh

则可直接执行该文件了: ./test1.sh

或者:

1
source test1.sh

(用source命令)

或者:

1
. test1.sh

(用点命令,注意点后面有空格

编写Shell脚本,显示当前的日期时间、执行路径、用户账号及所在的目录位置

源代码test2.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

#This script is a test!

echo “Date and time is :”

date #date为hell命令,显示当前日期

echo “The executable path is :”$PATH #环境变量PATH的值

echo “Your name is :`whoami`” # whoami是shell命令,执行结果是当前用户名

echo “Your current directory is :”

pwd # pwd是shell命令,显示当前路径

#end

注意:whoami用的是`这个符号(数字1前面的那个符号,即倒引号)。

课堂作业:

用同学们的学号命名一个脚本文件,如17240000.sh,并输入以下信息:(ctrl+空格,启动输入法)

1
2
3
4
5
6
7
8
9
#!/bin/bash

#This script is about me!

echo “我的班级是:17计应1班”

echo “我的学号是:17240000”

echo “我的名字是:张三”

编写Shell脚本,观察内部变量的作用。

源代码test3.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

echo “Number of parameters is” $# # $#为参数个数

echo “the file name is” $0 #$0为文件名

echo “Parameters as a single string is” $\ #$\为参数组成的字符串**

echo “the first parameter is” $1 #$1第1个参数

echo “the second parameter is” $2 #$2第2个参数

echo “the third parameter is” $3 #$3第3个参数

若输入如下命令:

1
bash test3.sh a b c

则,运行结果为:

Number of parameters is 3

Program name is test3.sh

Parameters as a single string is a b c

the first parameter is a

the second parameter is b

the third parameter is c

4) 编写Shell脚本,观察内部变量的作用。Shell脚本中只带了一个参数(名字),在屏幕上显示这个名字:

源代码test4.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

#Name display program

if [ $# -eq 0 ] #若参数个数为0

then

echo “Parameter not provided,the file name is” $0

else

echo ”the first parameter name is $1”

fi #if语句最后要有fi结束

若输入如下命令:

1
bash test4.sh abc def

则,运行结果为:

the first parameter name is abc

5) 编写Shell脚本,判断当前目录下的文件是目录还是文件。

源代码:file_or_dir.sh

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash 
for i in ./* #声明变量i,*为shell下的通配符./*表示当前目录下所有文件名,i的取值为所有文件名,此处./可省略
do
if [ -f $i ] #若$i文件存在且为普通文件则真($i就是文件名),注意:缩进必须用tab键,[后有空格,]前有空格
then
echo "$i is a file"
elif [ -d $i ] #若文件$i存在且为目录文件则真
then
echo "$i is a directory"
fi
done #do语句要以done结束

运行方式:命令

1
bash file_or_dir.sh

6) 编写Shell脚本,实现目录的压缩、解压和删除功能。

源代码:case_and_if.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/bin/bash 

# Interactive program to restore, backup, or delete a directory

echo "Welcome to the menu Driectory Archive Program"

while true

do

# Display a Menu

echo

echo "Make a Choice from the Menu below"

echo _

echo "1 Backup directory "

echo "2 Restore directory "

echo "3 Delete directory"

echo "4 Quit"

echo



# Read the user's selection

echo -n "Enter Choice: " #-n表示不换行输出

read CHOICE

case $CHOICE in [1-3] ) #注意:括号的用法

echo # Read and validate the name of the directory

echo -n "What directory do you want? "

read WORKDIR

esac #case语句的结尾



case "$CHOICE" in

1) echo " Backuping... "

if [ ! -d "$WORKDIR" ]

then

echo "Sorry, $WORKDIR is not a directory"

continue # continue,继续下一次do循环

fi #if语句的结尾

tar -cvzf $WORKDIR.tar.gz ./ $WORKDIR;; #两个分号

2) echo " Restoring..."

tar -xvzf $WORKDIR.tar.gz ./;;

3) echo "Deletting..."

rm -r $WORKDIR;;

4) echo "Quitting"

break;; # break,退出do循环

esac #case语句的结尾

done

2. 拓展训练

在上述代码的基础上,实现以下菜单功能:

1 Copy directory

2 Move directory

3 Delete directory

4 Quit

其中,菜单1和2需要询问源目录和目标目录是什么,菜单3询问要删除的目录是什么?并在课堂上完成,调试通过后,将运行结果截屏,将源程序和截屏的图片上传到CC网对应网盘中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/bin/bash 

while true

do

#This is a menu

echo

echo "Make a Choice from the Menu below"

echo _

echo "1 Copy directory"

echo "2 Move directory"

echo "3 Delete directory"

echo "4 Quit"

echo

#Read the user's selection

echo -n "Enter Choice:"

read CHOICE

case $CHOICE in [1-2])

echo

echo -n "源路径:"

read FORMDIR

echo -n "目标路径:"

read TODIR

esac

case $CHOICE in [3])

echo

echo -n "删除的路径:"

read DELDIR

esac

case "$CHOICE" in

1)echo "Copying..."

cp -a $FORMDIR $TODIR;;

2)echo "Moving..."

mv -i $FORMDIR $TODIR;;

3)echo "Deleting..."

rm -ir $DELDIR;;

4)echo "Quitting..."

break;;

esac

done

MakeFile 文件

为什么使用MakeFile?

前面已经实现了在Linux下使用编辑器编写代码,使用GCC把代码编译成可执行文件,那么,所有的工作看似已经完成了,为什么还需要Make这个工程管理器呢?

所谓工程管理器,顾名思义,是指管理较多的文件的。同学们可以试想一下,有一个上百个文件的代码构成的工程,如果其中只有一个或少数几个文件进行了修改,按照之前所学的GCC编译工具,就不得不把这所有的文件重新编译一遍,因为编译器并不知道哪些文件是最近更新的,而只知道需要包含这些文件才能把源代码编译成可执行文件,于是,程序员就不能不再重新输入数目如此庞大的文件名以完成最后的编译工作。人们就希望有一个工程管理器能够自动识别更新了文件代码,同时又不需要重复输入冗长的命令行,这样,Make工程管理器也就应运而生了。

实际上,Make工程管理器也就是个自动编译管理器,这里的自动是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件的内容来执行大量的编译工作。用户只需编写一次简单的编译语句就可以了。它大大提高了实际项目的工作效率,而且几乎所有Linux下的项目编程均会涉及它,希望同学们能够认真学习本节内容。

实训

  1. 不用Makefile文件直接编译
    1) 用vi在同一目录下编辑两个简单的文件,具体代码为:
    a、建立文件hello.c,内容如下:

    1
    2
    3
    4
    5
    #include "hello.h" 
    int main()
    {
    printf("Hello everyone!\n");
    }

b、建立文件hello.h ,内容如下:

1
C#include <stdio.h>

2) 在shell命令行中用gcc尝试编译,使用命令:

1
gcc hello.c -o hello

​ (或:gcc -o hello hello.c )
3)运行hello可执行文件查看结果

1
./hello

4) 删除此次编译的可执行文件:

1
rm hello
  1. 不使用变量替换实现makefile(也可以是Makefile)

1) 新建立目录,命名为xm7
2) 在xm7目录中建立三个文件:xm7.c、xm7.h、makefile
a、 touch xm7.c
b、 touch xm7.h
c、 touch makefile
3) 编辑三个文件的内容
a、vi xm7.c,内容如下:

1
2
3
4
5
#include "xm7.h" 
int main()
{
printf("Hello everyone!\n");
}

b、vi xm7.h,内容如下:

1
#include <stdio.h>

c、vi makefile,内容如下:(#注意gcc前应该添加一个Tab,不能是空格)

1
2
3
4
5
6
xm7:xm7.o                      #xm7依赖于xm7.o
gcc -o xm7 xm7.o #从xm7.o生成xm7使用的命令,-o后面跟着可执行文件的名字xm7
xm7.o:xm7.c #xm7.o依赖于xm7.c ,
gcc -c xm7.c #从xm7.c生成xm7.o使用的命令,-c表示仅编译、不链接,生成目标文件xm7.o
clean:
rm xm7.o xm7 #目标clean命令的具体操作

4) 用make命令验证所编写的Makefile是否正确,并运行该程序:

1
2
3
make                    #make后面省略目标,则默认为只想第一个目标xm7
make xm7 #make+目标名
make clean

5) 删除此次编译的可执行文件xm7和目标文件xm7.o:

1
make clean

Linux文件系统编程

全缓冲文件I/O

1) 向缓冲区中输入字符
2) 当往缓冲区中写的字符数目超过缓冲区大小的时候,才执行输出。
3) 可以手工计算出缓冲区大小(341*3+1=1024)
4) 代码:(fullbuffer.c)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h> 
int main()
{
int i=0;
for(i=0;i<379;i++)//每次向缓冲区内写三个字符
{
if(i>=100)
fprintf(stdout,"%d",i);
else if (i>=10)
fprintf(stdout,"0%d",i);
else if (i>=0)
fprintf(stdout,"00%d",i);
}
while(1);
}

可以看到终端屏幕共输出了1024字节大小(i=340时)的内容,多余的内容没有输出,这就验证了全缓存的特点:当填满I/O 缓存后才进行实际的I/O操作,可计算出此时缓冲区为1024字节。

可以看到终端屏幕共输出了1024字节大小(i=340时)的内容,多余的内容没有输出,这就验证了全缓存的特点:当填满I/O 缓存后才进行实际的I/O操作,可计算出此时缓冲区为1024字节。

  1. 标准文件输入输出实验
    本实验通过一个简单的copy程序,完成文件的复制。
    需要了解基本的标准I/O文件读写的基本步骤,深入了解标准IO文件读写的基本原理。还需要学习如何判断文件是否结束及掌握标准I/O函数。
    1) 判断文件结束有三种方式:
    a)

    1
    2
    3
    char p[1024];
    while (fgets(p,1024,src)!= NULL) //fgets函数成功返回p;若遇文件结束或出错则返回NULL(即0)。
    fputs(p,des1);

    b)

    1
    2
    3
    int c;
    while((c=fgetc(src))!=EOF) //fgetc函数成功则返回所读的字符;否则返回EOF(即-1)
    fputc(c,des2);

    c)

    1
    2
    3
    4
    5
    6
    while((n=fread(s,1,20,src)) == 20)   // fread函数成功返回实际读取的记录数;失败返回EOF
    {
    // printf("%d\n",t++);
    fwrite(s,1,n,des3);
    }
    fwrite(s,1,n,des3);

    2) 要拷贝一个文件,即要有源文件和目标文件,使用fopen分别打开两个文件,一个文件被读,一个文件被写。完成文件的复制后须将这两个文件都关闭。
    源代码:(filecopy.c)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
       #include <stdio.h> 
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #define maxsize 5
    int main(int argc,char *argv[])
    {
    FILE *fp1,*fp2;
    char ch[maxsize]; //定义字符数组ch
    if(argc!=3) //运行程序时,必须提供三个参数,否则退出。
    {
    printf("command error!\n");
    return -1;// exit(-1);
    }

    if((fp1=fopen(argv[1],"r"))==NULL) //运行程序时提供的第一个参数必须是可读文件的名字
    {
    printf("file %s cannot open",argv[1]);
    return -1;//exit(-1);
    }

    if ((fp2=fopen(argv[2],"w"))==NULL) //运行程序时提供的第二个参数必须是可写文件的名字
    {
    printf("cannot creat file %s",argv[2]);
    return -1;// exit(-1);
    }

    while(fgets(ch,maxsize,fp1)!=NULL) //从文件1中一次读取maxsize个字符存入ch字符数组,
    fputs(ch,fp2); //若文件fp1没有结束,就继续读并写入文件fp2。
    //将从文件fp1中读取的字符串写入文件fp2

    fclose(fp1);
    fclose(fp2);
    return 0;
    }

编译程序:

1
gcc -o filecopy filecopy.c

运行程序:

1
./filecopy file1 file2

则实现了将文件file1复制到文件file2。(file2若不存在则会自动新建)
用cat file1 file2 验证结果。

课堂练习:

参照以上程序,实现将两个文件拷贝合并至一个文件的程序,文件用自己学号命名,调试通过后,将运行结果截屏,将源程序和截屏的图片上传到CC网中的项目8文件夹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define maxsize 5
int main(int argc,char *argv[])
{
FILE *fp1,*fp2,*fp3;
char ch[maxsize]; //定义字符数组ch
if(argc!=4) //运行程序时,必须提供三个参数,否则退出。
{
printf("command error!\n");
return -1;// exit(-1);
}

if((fp1=fopen(argv[1],"r"))==NULL) //运行程序时提供的第一个参数必须是可读文件的名字
{
printf("file %s cannot open",argv[1]);
return -1;//exit(-1);
}

if((fp2=fopen(argv[2],"r"))==NULL)
{

printf("file %s cannot open",argv[2]);
return -1;//exit(-1);
}

if ((fp3=fopen(argv[3],"w"))==NULL) //运行程序时提供的第二个参数必须是可写文件的名字
{
printf("cannot creat file %s",argv[3]);
return -1;// exit(-1);
}

while(fgets(ch,maxsize,fp1)!=NULL) //从文件1中一次读取maxsize个字符存入ch字符数组,
fputs(ch,fp3); //若文件fp1没有结束,就继续读并写入文件fp2。
//将从文件fp1中读取的字符串写入文件fp2
while(fgets(ch,maxsize,fp2)!=NULL)
fputs(ch,fp3);

fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;

}

3.拓展训练
编程读写一个文件test.txt,每隔1秒向文件中写入一行数据,类似这样:
1, 2017-1-30 15:16:42
2, 2017-1-30 15:16:43
该程序应该无限循环,直到按Ctrl-C中断程序。下次再启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号,比如:
1, 2017-1-30 15:16:42
2, 2017-1-30 15:16:43
3, 2017-1-30 15:19:02
4, 2017-1-30 15:19:03
5, 2017-1-30 15:19:04
要追加写入文件,同时要读取该文件的内容以决定下一个序号是几,应该用什么模式打开文件?
1) 首先判断一下打开的文件是否为新文件,如果是新文件,就从序号1开始写入;如果不是新文件,则统计原来有多少行,比如有n行,然后从序号n+1开始写入。以后每写一行就把行号加1。
2) 获取当前的系统时间需要调用函数time(),得到的结果是一个time_t类型,其实就是一个大整数,其值表示从UTC时间1970年1月1日00:00:00(称为UNIX的Epoch时间)到当前时刻的秒钟数。然后调用localtime()将time_t所表示的UTC时间转换为本地时间(我们是+8区,比UTC多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。具体用法请查阅相关手册。time和localtime函数需要头文件time.h。
(UTC时间是世界统一时间、国际协调时间Coordinated Universal Time,不属于任何时区)
3) 调用sleep(n)可使程序睡眠n秒,该函数需要头文件unistd.h。

源代码:(writetest.c)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(int argc, const char *argv[])
{
FILE *file;
struct tm *t1;
time_t t;
char buf[100];
int line=1;
int c;
memset(buf, 0, sizeof(buf)); //将数组buf的存储空间清0
if ((file = fopen("test.txt", "a+")) == NULL)
{
perror("failed to open test.txt");
return(-1);
}
while ((c = getc(file)) != EOF) //从打开的文件中读一个字符,若不是结束符,则表示不是新文件
if (c == '\n') //否则直接跳到while(1)循环。若为换行符,则行号加1
line++;
while (1)
{
time(&t);
t1 = localtime(&t);//获取当前世界时间
sprintf(buf, "%d, %d-%d-%d %d:%d:%d\n", line++, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); //按照指定格式写入buf存储区
fwrite(buf, sizeof(char), strlen(buf), file); //将buf的数据写入打开的文件test.txt中
fflush(file); //将缓冲区中的数据写回file文件中,清缓冲区
sleep(1);
}
return 0;
}

编译:

1
gcc -o writetest writetest.c

运行:

1
./writetest

终止程序执行:ctrl+c
查看执行结果:cat test.txt
再运行程序、查看结果

练习:

参照以上程序,实现一个公司上下班打卡记录的程序,员工ID(8位)通过键盘输入(真实打卡是直接刷卡即可),记录文件名称为record.txt,其中包括打卡时间(精确到秒)和打卡员工的ID号。程序用自己学号命名,调试通过后,将运行结果截屏,将源程序和截屏的图片上传到CC网对应目录中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(int argc, const char *argv[])
{
FILE *file;
struct tm *t1;
time_t t;
char buf[100];
char id[10];
int line=1;
int c;
memset(buf, 0, sizeof(buf)); //将数组buf的存储空间清0
if ((file = fopen("test.txt", "a+")) == NULL)
{
perror("failed to open test.txt");
return(-1);
}
while ((c = getc(file)) != EOF) //从打开的文件中读一个字符,若不是结束符,则表示不是新文件
if (c == '\n') //否则直接跳到while(1)循环。若为换行符,则行号加1
line++;
while (1)
{
printf("请输入工号:\n");
gets(id);
fprintf(file,"工号:%s\n",id);
time(&t);
t1 = localtime(&t);//获取当前世界时间
printf("%d, %d-%d-%d %d:%d:%d\n", line++, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec);
sprintf(buf,"%d, %d-%d-%d %d:%d:%d\n", line++, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec ); //按照指定格式写入buf存储区
fwrite(buf, sizeof(char), strlen(buf), file); //将buf的数据写入打开的文件test.txt中
fflush(file); //将缓冲区中的数据写回file文件中,清缓冲区
sleep(1);
}
return 0;
}

编译后运行即可。

什么是嵌入式系统?列举3种典型的嵌入式产品。

嵌入式产品,如:手机、机顶盒、PDA等

嵌入式系统的概念:嵌入式系统是以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。

嵌入式系统有什么共同的特点?

嵌入式系统的共同特点:

  • ​ 软硬件一体化
  • ​ 有多种硬件平台和软件平台
  • ​ 对成本敏感
  • ​ 有实时性和可靠性要求
  • ​ 操作系统可以裁剪
  • ​ 专用开发工具

嵌入式系统与个人计算机有哪些不同?

嵌入式系统与PC机的不同:

  • ​ PC机软件、硬件比较单一,而嵌入式系统的软件、硬件平台很多
  • ​ 用途有不同
  • ​ 结构有很大差异
  • ​ 应用领域不同
  • ​ 成本不同
  • ​ 性能不同。

影响手机功耗的有哪些因素?(至少说5个)

影响手机功耗的主要因素:

  1. LCD显示器
  2. 嵌入式微处理器和DSP微处理器
  3. 基带处理器
  4. WiFi、蓝牙等
  5. 内存
  6. 外部接口

在设计手机的过程中想降低功耗,有什么方法?(至少说5个)

设计环节减少功耗的主要方法:

  1. 采用低功耗的背光源
  2. 选择采用低功耗微处理器
  3. 采用低功耗SDRAM
  4. 动态控制电源电压
  5. 动态控制工作频率
  6. 采用嵌入式操作系统来控制硬件降低功耗

完结。