Liunx文件目录
- home是家目录,是个人目录,建议在通常情况下个人相关的内容也是保存在该目录中,因为其它目录大都是系统相关的,使用时容易导致混乱,而且需要相关权限
- 特别地,前面说明的家目录(个人目录)路径为“/home/用户名/”,见下图,图中的例子目录是/home/embedfire 。也就是说,在 Ubuntu 系统下,用户的个人目录都在“/home”下,并且按照用户名命名,如果系统下有多个用户 A、B、C 并且它们都有个人目录的话,那么它们的个人目录路径默认就是“/home/A”,“/home/B”,“/home/C”。
- 如软件工具默认安装在/usr/bin 目录,软件工具的配置文件可能位于/etc 目录,甚至系统的日常使用如插入 U 盘或光盘,又发现它们不会像 Windows 有独立的盘符可以访问,而是默认挂载在/media 或/mnt 目录下。
根目录结构
整个 Linux 系统有且只有一棵从根目录开始的目录树,如下图所示
- 给电脑插入 U 盘,系统会自动把 U 盘挂载在“/media/用户名/”目录下,打开该目录即可访问 U盘进行读写
根目录的内容如下图:
文件类型
在Linux下一切皆文件
- 普通文件
如文本文件,bin 文件等 - 可执行文件
可执行文件包括脚本和应用程序,这些文件可被系统加载运行,类似 Windows 下的 bat 脚本、exe程序文件等。 - 链接文件分为硬链接和软链接:
• 硬链接是指同一个文件的不同别名。
• 软链接文件有类似于 Windows 的快捷方式。它实际上是 一 个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。 - 目录文件
在 Linux 下目录也是文件。 - 设备文件
硬件设备也是文件,通过打开对应的设备文件可以初始化设备,部分设备还可以通过读写设备文
件实现对硬件的控制
文件扩展名
在 Windows 下习惯通过文件的后缀名来判断可以使用什么软件打开对应的文件,而 Linux 下没有
这样的要求,便 Linux 下为了容易区分和兼容用户使用 Windows 的习惯,我们还是会用扩展名来
表示文件类型。举例如下:
- 后缀.tar、.tar.gz、.tgz、.zip、.tar.bz 表示压缩文件,创建命令一般为 tar,gzip,zip 等。在压
缩文件中的后缀名来通常表示自身由什么压缩格式打包的,以便解压时方便选择要使用的
命令。 - .sh 表示 shell 脚本文件,通过 shell 语言开发的程序。
- .pl 表示 perl 语言文件,通过 perl 语言开发的程序。
- .py 表示 python 语言文件,通过 python 语言开发的程序。
- .html、.htm、.php、.jsp、.do 表示网页语言的文件。
- .conf 表示系统服务的配置文件。
- .rpm 表示 rpm 安装包文件。
用户组与文件权限
- 在etc文件夹下有三个重要的文件:/etc/passwd ;/etc/shadow;/etc/group
- /etc/passwd用于存放用户帐号信息,/etc/shadow 用于存放每个用户加密的密码,/etc/group用于 存放用户的组信息。
- 开机登入时,先在password上查找用户名是否正确,正确的话获取UID;
- 然后在group文件获取gid;
- 前两部完成后,在shadow文件下查看密码是否正确
用户及用户组
- 用户按照使用者分为:管理员,系统用户,普通用户
- 在 Linux 中,每个用户都有一个特定的编号——UID,用于标识一个系统用户。Linux 将标号 0 分配给 root 用户的 uid,它可以分配给每个用户不同的权限,因此每个用户可进行的操作也不同。
- UID取值范围: root 0; 系统用户:1~999;普通用户1000以上
- 每个用户可以对应多个分组
文件权限
- Linux 的文件属性,可以分为读权限、写权限、执行权限。
- 读权限以及写权限,基本上和 Windows操作系统是一样的。
- 执行权限,是指可以加载到内存中,并由操作系统加载程序执行的文件。
在 Windows 操作系统中,我们接触最多的应该是后缀为.exe 的文件。但是对Linux 来说,它并不是通过后缀名来识别文件类型的,如果我们想要执行某个可执行文件,则需要为其添加执行权限,即勾选前面的“允许作为程序可执行文件"。 - 关于 Linux 文件权限,还需要分三种情况:文件拥有者(owner),分组成员(groups)
以及其他分组成员(other)。 - 我们可以通过 chmod 命令在终端快速地修改文件的权限。
- 如果给所有人添加可执行权限:chmod a+x 文件名;
如果给文件所有者添加可执行权限:chmod u+x 文件名
r w x
Linux命令行
在早期的 Unix 系统与用户就是通过 Shell 进行交互的,如下图所示,Shell 对外接受用户输入的命令,对内通过“系统调用”传递给内核,内核执行操作后把输出通过 Shell 呈现给用户,也就是说,Shell 就是一个中间人。而 Shell 的英文原意“壳”,也是为了把它与内核区分开来。
Shell、终端(Terminal)或控制台(Console),严格来说它们实际上不是同样的东西,但只要明白,当我们说打开 Shell、终端或控制台的时候,通常就是为了使用命令行控制系统。它们的严格区分如下,了解下即可:
- Shell:指命令行解释器,常见的解释器有 bash,sh,在 Ubuntu 系统默认用的是 bash 解释器,所以有时说 bash 也是指命令行。
- 终端(Terminal):通常指用来运行 Shell 的程序,示场景的不同有不一样的名称,如 Ubuntu系统自带的叫本地终端,嵌入式开发板常常提供串口进行输入输出的串口终端,通过网络访问的 ssh 终端。
- 控制台(Console):特指某些终端,通常是指它的物理形态,如带键盘和显示器的物理设备。
通过快捷键 Ctrl+Alt+T,可以快速打开一个命令行终端;
命令提示符
- pwd 输出当前所在目录
- ls 显示当前目录所有内容
- 每个命令都会带有一个“-h”或者“–help”的参数,可以用来打印一些帮助说明
自动补全
- 按一下“Tab”键时如果只有一个匹配的内容时它会自动补全,按两下“Tab”键则会列出所有的匹配项。
- Tab”键除了用来补全命令名,还可以自动补全路径,如我们使用 cd 命令输入“/home”参数时,先输入“/ho”然后按下“Tab”键,它会把“/ho”自动补全为“/home”路径名
命令的退出与取消
在应用中我们有时会想要中止命令的执行,或者命令输入到一半的时候觉得输错了不想继续,这时我们都可以通过“Ctrl”+“c”的组合键来结束。
命令究竟是什么
在终端中,我们使用 which 命令可以查看指定命令的路径,如查看 ls、pwd、cd 命令:
ls 命令实际是/bin/ls 程序,pwd 命令实际是/bin/pwd 程序,而 which cd 命令没
有输出,因为 cd 命令是 Shell 自己内部的程序
-
我们在 Shell 中输入 ls 命令与输入/bin/ls 的作用是一样的,当我们输入 Shell 时,它会到预定的目录下查找有没有该程序,如果有就使用命令选项及参数调用该程序执行,并把程序的输出再呈现出来。而这个预定的目录我们可以通过如下命令来查看:
echo $ PATH //echo 是输出命令,而"$PATH" 是一个变量,表示输出变量内容!
-
“$ PATH”是终端使用的路径环境变量,它使用“: ”进行分隔,表示 Shell 将会在这些路径下寻找命令程序,在其中我们可以看到/bin 路径。也就是说,“$PATH”路径环境变量让我们输入命令时省去了输入完整路径的麻烦,而命令的本质大都是在文件系统中的一些应用程序。
常用命令
cd
把终端当前所在的路径切换至目标路径,比如:cd /home/embedfire/test
mkdir 命令
它可以在文件系统中创建一个新的目录
其命令格式如下:mkdir [-p] 目录名
- 命令格式中的“目录名”就是要创建的目录路径,“-p”选项可以不输入,若使用了“-p”选项,当创建的目录名包含的上级目录不存在时,它会自动创建所有不存在的目录
touch命令
touch 命令可以创建不存在的文件,或者 touch 通过参数修改目录或文件的日期时间,就是摸一下,更新它的时间。
它的命令格式如下:touch 文件名
ls命令
显示指定目录下的内容(文件及子目录) ,还可以查看文件大小,修改日期等等信息
ls 命令格式如下:ls [选项] [目录]
当“目录”参数省略时,它会列出当前目录的内容。
-rw-r--r-- 1 jing jing 8980 4月 12 07:26 examples.desktop
drwxr-xr-x 2 jing jing 4096 4月 12 15:29 公共的
-
第一字段:文件属性
文件属性共有十个字符,第一个字符代表文件的类型,字符“-”表示该文件是一个普通文件;字符“d”是 dirtectory(目录) 的首字符,表示该文件是一个目录。 -
后面的九个字符,每三个为一组,分别表示文件拥有者的权限、文件所属组拥有的权限以及其他用户拥有的权限。字符“r”代表的是读(read)权限,字符“w”代表的是写(write)权限,字符“x”代表的是执行(execute)权限
-
第二字段:链接占用的节点/子目录的个数
第二字段的含义,主要取决该文件的类型,如果是文件的话,则表示该文件所具有的硬连接数。某个文件的第二字段如果等于 1 的话,代表没有其他指向该文件的硬连接。
-
第三字段和第四字段:文件拥有者和文件所在的组
-
第五字段:文件所占用的空间 (以字节为单位)
第五字段表示文件大小,在 Linux 中,目录是一个特殊的文件。 -
第六字段:最近访问(修改)时间
-
第五字段表示文件最近访问的时间,使用 touch 命令,可以修改文件的第六字段。
cat命令
cat 命令是 concatenate 的简写,译为串联,即它可以把两个内容串联起来,我们通常使用它在终端下输出文件的内容进行查看。cat不能查看目录
命令格式为:cat 文件名
echo命令
echo 命令的功能是在终端上打印一段文字,也可以把终端的变量内容打印出来
其命令格式如下:
- echo " 字符串"
- echo 字符串
- echo $ 变量名
使用 echo 命令时,带双引号和不带双引号的效果是一样的,使用引号时,要注意用英文符号
输出重定向到文件
把命令执行的结果保存到文件进行分析,这时我们可以使用输出重定向到文件的控制符“>”或“»”,其中“>”会直接用输出覆盖原文件,而“»”则把输出追加到原文件的末尾。
使用格式如下:
- 命令 > 文件名
- 命令 >> 文件名
重定向时文件不存在会自动创建。
rmdir 命令
rmdir 命令是 remove directory 的简写,它的功能是删除空的目录。
- 命令格式如下:rmdir [-p] 目录名
-p 可以用来递归删除目录,如果子目录删除后其父目录为空时,也一同被
rmdir 命令只能够用来删除空目录
rm 命令
rm 命令是 remove 的简写,它的功能是删除一个或多个文件或目录。
- 其命令格式如下:rm [选项] 一个或多个文件/文件夹名
使用 rm 命令删除内容时,文件是会被直接永久删除的,它并不会放到回收站中再确认
它支持的选项如下:
• -i:删除文件或文件夹前,终端会逐一询问确认
• -r:将目录及其包含的子目录或文件全部删除
• -f:忽略不存在的文件,无需逐一确认
mkdir -p ABC/test //创建 ABC/test 目录
rm a.txt b.txt //直接删除 a.txt b.txt
3 rm –i c.txt d.txt //询问式删除 c.txt d.txt
当带有参数 i 时,则会有询问是否删除文件,如果是,输入 y;反之,则输入 n。
- 前面提到 rmdir 命令不能删除非空的目录,我们可以使用 rm 命令配合“-r”选项来完成:rm –r ABC/
sudo
sudo 命令是 switch user do 的简写,意思是切换用户去做某件事情
有时我们在执行命令时忘记添加 sudo 前缀,执行失败提示时才想起要加 sudo,这时可以使用
“sudo !!”的方式使用 sudo 权限重新执行上一条命令
cd /home # 切换至/home 目录
touch test.txt # 提示没有权限
sudo !! # sudo 加两个感叹号,重新使用 sudo 权限执行上一条命令
reboot/poweroff 命令
在终端上,reboot/poweroff 命令来控制系统的重启与关机
man命令
可用于查看 Linux 系统自带的参考手册,该手册包含非常丰富的内容,甚至在我们进行编程开发时还可以使用它来查看函数的接口
man 命令格式:man [要查询的内容]
在命令行中输入:man man #即使用man来查询man
下面截取了一段
在命令行中输入 man printf
输出的PRINTF(1),表示是man的第一章的printf
如果查第三章中库调用需要在终端输入:
- man -s 3 printf
- man 3 printf
-s可以省略
apt 及 yum 包管理工具
deb 包、dpkg 及 apt
在 Linux 操作系统中,最常见的两种包分别是 deb 和 rpm。
在 Debian、Ubuntu 等 Linux 发行版中,通常使用 deb(debian)形式的软件包
包提供了操作系统的基本组件,以及共享的库、应用程序、服务和文档,当用户需要时,可以运行特定的指令来安装。
- 对于下载到本地和已经安装的软件包可以使用dpkg命令
sudo dpkg -i xxxx.deb
- apt 能够自动从互联网的软件仓库中搜索、安装、升级、卸载软件,它会咨询软件仓库,并能安装软件时的模块及依赖问题。
sudo apt-get install 软件名
- 概括起来可以这么理解,deb 是软件包,dpkg 是手动安装工具,apt 是自动安装工具。
rpm 包、rpm 及 yum
在 RedHat,Fedora,Centos 等派系的 Linux 发行版中,通常使用 rpm(RedHat PackageManager) 形式的软件包
- rpm 与 dpkg 的功能类似,同样是主要用于对已下载到本地和已经安装的软件包进行管理。
rpm -ivh xxxx.rpm
- yum(Yellow dog Updater, Modified)包管理工具,功能与 apt 工具类似,它会咨
询软件仓库,并能安装软件时的模块及依赖问题。
yum install 软件名
apt 工具的使用
- apt-get 工具:主要负责软件包的的安装、卸载以及更新等事务。
- apt-cache 工具:用于查询软件包的相关信息。
- apt-config 工具:用于配置所有 apt 工具。
apt-get 安装与删除软件包
apt-get 工具安装程序,具体的命令语法:sudo apt-get install 软件包名
- apt-get install 会扫描本地存放的软件包更新列表/var/lib/apt/lists/,找到最新版本的软件包,然后检查软件包依赖关系,找到支持该软件正常运行的所有软件包,并从镜像源地址中下载所需的软件包,最后解压软件包,自动完成应用程序的安装和配置。
apt-get remove
具体的命令语法如下:sudo apt-get remove 软件包名
apt-cache 查询软件包信息
apt-cache 工具配合对应的子命令,可以实现查找,显示软件包信息及包依赖关系等功能
例如,可通过如下命令搜索支持 ifconfig 命令的软件包:apt-cache search ifconfig
直接使用 apt 命令
在 Ubuntu 16.04 中就引入了 apt 命令,apt 是集 apt-get、apt-cache 和 apt-config 各工具之所长的工具
apt 命令比 APT(上面的apt-get等) 包管理工具更加精简
sudo apt install vim #安装Vim
Ctrl”+“z”强制退出vim编辑器。
软件源及其修改
• 清华大学镜像源:https://mirrors.tuna.tsinghua.edu.cn
• 中国科技大学镜像源:https://mirrors.ustc.edu.cn
• 阿里云镜像源:https://opsx.alibaba.com/mirror
在 Ubunut 下, 软 件 源 的 配 置 是 记 录 在 文件/etc/apt/sources.list 中的
Vim
- vi 文件名 #若文件存在则打开,文件不存在则创建
- vim 文件名字 #若文件存在则打开,文件不存在则创建
退出
注意若开启了输入法,要先把输入法设置成英文:
- “Ctrl”+“z”直接强制退出。
- 按下退出键“Esc”,Vim 会进入到“一般模式”。
- 输入英文冒号“:”,Vim 会进入到“命令行模式”。
- 输入强制退出命令“q!”,即字母“q”及英文叹号“!”。
- 按回车执行命令,会退出 Vim,返回到终端。
输入内容
- 按下退出键“Esc”进入“一般模式”。
- 输入一般命令“i”,即直接按字母“i”,进入“插入模式”,如下图所示。
- 随意输入一些内容。
- 按下退出键“Esc”再次进入“一般模式”。
- 输入英文冒号“:”,Vim 会进入到“命令行”模式。
- 输入保存退出命令“wq”。
- 按回车执行命令,会退出 Vim,返回到终端。
Vim 的三种模式
- 一般模式(normal mode):一般模式用来浏览文本,查找内容,但是不可以编辑,在该模式下的键盘输入会被当成快捷键,如复制粘贴等。打开 Vim 时,默认是工作在一般模式。
- 插入模式(insert mode):插入模式下具有普通编辑器的功能,该模式下的键盘输入会被当成文本内容。
- 命令行模式(command-line mode):命令行模式支持保存、退出、替换等命令,以及 Vim 的高级功能。
插入模式
一般模式
命令行模式
按下键盘的冒号键“:”就可以进入命令行模式
磁盘管理
-
df命令可以查看所有的存储设备以及其挂载点
-
du命令可以查看当前文件夹下所有文件的使用量
# 直接使用du命令的话,会把所有的文件等列出来,比较多,可以使--max-depth=a层数来限制 #加入-h显示的是,k,G等容量 $ du --max-depth=1 #只显示一层目录 16 ./笔记 5700836 ./linux 5700856 . $ du -h --max-depth=1 16K ./笔记 5.5G ./linux 5.5G .
-
新加入的硬盘设备在dev目录下,u盘这种移动设备在根目录下的media文件夹下,media文件夹下的内容会自动挂载
-
如果对u盘进行类似分区的操作,需要先挂载u盘时,一般直接挂载分区,而不会是前面的sd*
比如挂载sda时,应挂载其下的分区sda1和sda2
<
-
挂载命令:mount
sudo mount /dev/sda1 /mnt # 前面是需要挂载的,后面是挂载的目录 # 挂载过程中的中文可能会出现乱码的情况,可以制定相应的编码格式 sudo mount -O iocharset=utf8 /dev/sda1 /mnt #O为大写
-
卸载命令:umount
sudo umount /mnt #mnt为相应的挂载点
Ubuntu新添加硬盘
-
文件/etc/fstab 详细的记录了 Ubuntu 中硬盘分区的情况
-
在对一块新硬盘使用时,流程如下:
-
fdisk 在创建分区时
$ sudo fdisk /dev/sda
-
根据提示和帮助信息可以按n创建新的扇区,但是确定容量时,根据扇区确
-
一个扇区等于512个字节
-
比如分区的大小想确定为1G,那么1G容量对应的扇区数如下:
1 G = 1024 M = 1024 ∗ 1024 K B = 1024 ∗ 1024 ∗ 1024 B = 1073741824 B 扇区数 = 1073741824 / 512 = 2097512 1G=1024M=1024*1024KB=1024*1024*1024B=1073741824B \\ 扇区数=1073741824/512=2097512 1G=1024M=1024∗1024KB=1024∗1024∗1024B=1073741824B扇区数=1073741824/512=2097512
-
确定了第一个扇区的起始位置,在加上所需的扇区数,就是最后一个扇区的扇区数,比如上图中的第一个扇区是2048,分配1G的空间需要2097512个扇区,所以最后一个分区就是2048+2097512
-
w为保存退出,退出之后可以通过fdisk -l 来查看新创建的分区
linux连接文件
- Linux有两种连接文件:符号连接(软连接)和硬链接
- 软连接类似Windows下的快捷方式,硬连接在在我看来就是映射存储设备的同一个inode
- 硬连接创建好之后,更改一个,所有的都被更改,删除的话需要把所有的硬连接和原文件都删除,才能彻底删除,删除原文件并不会影响硬连接的文件
Linux c编程
编写程序
-
使用的vim进行编写程序,首先设置以下vim
- vi/vim编辑器默认 TAB 键为 8 空格,我们改成 4 空格,打开文件/etc/vim/vimrc,在文件后面加上如下代码(修改时应使用管理员权限,代码写在endif后)
set ts=4
- vim显示行数,在上述文件添加以下代码
set nu
- 修改后的/etc/vim/vimrc最后部分如下:
" Source a global configuration file if available if filereadable("/etc/vim/vimrc.local") source /etc/vim/vimrc.local endif set ts=4 set nu
-
通过vim会直接新建不存在的文件
编译程序
-
编译器使用的是gcc,在终端中输入gcc -v可以查看gcc的版本信息,其有x86架构的版本,也有ARM版本的,PC端一般都是x86版本的,如果想编译ARM版本的,需要交叉编译
-
gcc的编译流程为:预处理、编译、汇编和链接
- 预处理就是展开所有的头文件、替换程序中的宏、解析条件编译并添加到文件中
- 编译是将经过预编译处理的代码编译成汇编代码,也就是我们常说的程序编译
- 汇编就是将汇编语言文件编译成二进制目标文件。
- 链接就是将汇编出来的多个二进制目标文件链接在一起,形成最终的可执行文件
-
gcc 命令
gcc [选项] [文件名] gcc main.c -o main
- 主要的选项如下,可通过man命令具体查看
- -c:只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
- -o:<输出文件名>用来指定编译结束以后的输出文件名,如果不使用这个选项的话 GCC 默认编译出来的可执行文件名字为 a.out。(链接之后的可执行文件)
- -g:添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编译的时候生成调试所需的符号信息。
- -O:对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进
行优化,这样产生的可执行文件执行效率就高。 - -O2:比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。
-
执行的话使用命令“./+可执行文件”
-
如果有多个c文件和头文件,只需要使用gcc编译c文件,不需要编译h文件
Makefile
Makefile基础
-
工程编译的工具:make,描述哪些文件需要编译、哪些需要重新编译的文件就叫做 Makefile,Makefile 就跟脚本文件一样,Makefile 里面还可以执行系统命令。使用的时候只需要一个 make
-
在和c和头文件的文件夹内创建Makefile文件(文件名要对,makefile也行)
-
通过input.c,mian.c,calcu.c生成main可执行文件为例子:
- 首先在文件夹内创建Makefile文件,Makefile文件内容如下:
1 main: main.o input.o calcu.o # 两行一组,第一行冒号之前的是生成的文件,后面是它的依赖 2 gcc -o main main.o input.o calcu.o # 第二行开头是一个Tab按键,这一行是需要执行的操作 3 main.o: main.c 4 gcc -c main.c 5 input.o: input.c 6 gcc -c input.c 7 calcu.o: calcu.c 8 gcc -c calcu.c 9 10 clean: 11 rm *.o 12 rm main
- 文件的第一行是最终生成的可执行文件,最终需要生成的必须放在文件的第一个
- 此处必须使用Tab,不能使用空格
- 里面的gcc命令和普通的不太一样,需要生成的文件和依赖文件的位置不同
-
编写完Makefile后,直接使用make指令
Makefile语法
Makefile规则格式
-
Makefile 里面是由一系列的规则组成
目标…... : 依赖文件集合…… 命令 1 命令 2 ……
-
make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shell 进程去执行
-
make的执行过程大致如下:
- make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
- 当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件
- 当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标。
Makefile变量
-
变量示例如下:
1 #Makefile 变量的使用 2 objects = main.o input.o calcu.o 3 main: $(objects) #Makefile 中变量的引用方法是“$(变量名)” 4 gcc -o main $(objects)
- 注意等号前后的空格
-
赋值符“=”
1 name = ss1 2 curname = $(name) 3 name = ss2 4 5 print: 6 @echo curname: $(curname)
- “echo”前面加了个“@”符号,因为 Make 在执行的过程中会自动输出命令执行过程,在命令前面加上“@”的话就不会输出命令执行过程
- 调用make print的结果如下:
- 注意结果是ss2,不是ss1,如果想结果是ss1的话,需要使用下面的“ := ”
- 赋值符“=”的神奇之处!借助另外一个变量,可以将变量的真实值推到后面去定义。
- 也就是变量的真实值取决于它所引用的变量的最后一次有效值。
-
赋值符“:=”
1 name = ss1 2 curname := $(name) 3 name = ss2 4 5 print: 6 @echo curname: $(curname)
- 注意等号前后的空格
- 调用make print如下:
- 赋值符“ := ”会使用后面定义的变量,只能使用前面已经定义好的,这就是“ = ”和“ := ”两个的区别
-
赋值符“?=”
curname ?= zuozhongkai
- 上述代码的意思就是,如果变量 curname 前面没有被赋值,那么此变量就是“zuozhongkai”,如果前面已经赋过值了,那么就使用前面赋的值。
-
变量追加“+=“
objects = main.o inpiut.o objects += calcu.o
- 一开始变量 objects 的值为“main.o input.o”,后面我们给他追加了一个“calcu.o”,因此变量 objects 变成了“main.o input.o calcu.o”
Makefile 模式规则
-
减少Makefile命令的重复书写,使用类似于统配符的方式来简化书写
-
示例如下:
1 objects = main.o input.o calcu.o 2 main: $(objects) #注意空格 3 gcc -o main $(objects) 4 5 %.o: %.c #注意空格
-
至少在规则的目标定定义中要有“%”,否则就是一般规则
-
目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串
-
比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件
Makefile 自动化变量
-
通过一行命令来从不同的依赖文件中生成对应的目标
自动化变量 描述 $@ 规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模
式中定义的目标集合。$% 当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,
那么其值为空。$< 依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么
“$<”就是符合模式的一系列的文件集合。$? 所有比目标新的依赖目标集合,以空格分开。 $^ 所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,
“$^”会去除重复的依赖文件,值保留一份。$+ 和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。 $* 这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模
式为 a.%.c,那么“$*”就是 test/a.test。 -
示例如下:
1 objects = main.o input.o calcu.o 2 main: $(objects) 3 gcc -o main $(objects) 4 5 %.o: %.c 6 gcc -c $< 7 8 clean: 9 rm *.o 10 rm main
Makefile 伪目标
-
Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,比如上面的clean
-
使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突
-
比如在Makefile的同级目录下有clean文件,那么当Makefile时就发现其已经存在,不需要执行下面的命令,因此下面的命令不会被执行
-
为了解决上述的问题就需要声明其为伪目标文件,示例如下:(第四行)
1 objects = main.o input.o calcu.o 2 main: $(objects) 3 gcc -o main $(objects) 4 .PHONY: clean #写成".PHONY : clean"也没有问题 5 %.o: %.c 6 gcc -c $< 7 8 clean: 9 rm *.o 10 rm main
Makefile 条件判断
-
条件判断两种语法如下:
-
<条件关键字> <条件为真时执行的语句> endif
-
<条件关键字> <条件为真时执行的语句> else <条件为假时执行的语句> endif
-
-
条件关键字有4个,分别是ifeq,ifneq,ifdef,ifndef
-
ifeq判断是否相等,ifneq判断是否不相等
-
ifeq用法如下,相等的话为真,ifneq用法与其相似,不相等为真
ifeq (<参数 1>, <参数 2>) ifeq ‘<参数 1 >’,‘ <参数 2>’ ifeq “<参数 1>”, “<参数 2>” ifeq “<参数 1>”, ‘<参数 2>’ ifeq ‘<参数 1>’, “<参数 2>”
-
-
ifdef判断变量是否为非空。ifndef判断变量是否为空
-
ifdef非空为真,ifndef空为真
ifdef <变量名>
-
Makefile函数使用
-
Makefile 中的函数是已经定义好的,不支持自定义函数
-
函数用法如下:
$(函数名 参数集合)或者${函数名 参数集合}
-
参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开
shell脚本
-
shell脚本类似windows的批处理文件,shell脚本就是将连续执行的命令写成一个文件。
-
shell脚本是个纯文本文件,命令从上而下,一行一行的开始执行。shell脚本扩展名为.sh。
-
shell的第一行一定是
#!/bin/bash #表示使用bash
shell相关语法
-
第一个shell脚本如下:
1 #!/bin/bash 2 echo "Hello Word "
- echo为在终端输出
-
交互式的shell脚本
1 #!/bin/bash 2 echo "Please input your name " 3 read name 4 echo "your name:" $name
- 第三行是读取终端的输入并给变量name,在第四行使用变量的时候不加括号
- 第四行中的 $name 放到双引号里面也可以
1 #!/bin/bash 2 read -p "input your name and age:" name age 3 echo "your name:$name,age=$age"
- 使用read -p 可以输出字符
-
数值计算
- shell仅支持整形,数值计算使用$((表达式))
1 #!/bin/bash 2 read -p "input two number:" first second 3 sum=$(($first+$second)) 4 echo "$first+$second=$sum"
- 第三行的等号前后均没有空格
-
test命令
- test命令用于查看文件是否存在、权限等信息,可以进行数值,字符,文件三方面的测试。
- &&和||命令:
- cmd1 && cmd2 当cmd1执行完并且正确,那么cmd2开始执行,如果cmd1执行完毕错误,那么cmd2不执行。
- cmd1 || cmd2 当cmd1执行完毕并正确,那么cmd2不执行,反之cmd2执行。
- && 和 || 可以连用
- cmd1 && cmd2 || cmd3 此条命令就是如果cmd1执行成功就执行cmd2,反之就执行cmd3
-
中括号[]判断符
- 示例如下:
1 #!/bin/bash 2 read -p "input two str:" first second 3 [ $first == $second ] && echo "yes" || echo "no"
- 注意第三行***[ ]里面的前后均有一个空格***,里面可以写==或者!=
- 但是需要注意的是[ ]里面的比较也会比较你带的分号,比如
1 #!/bin/bash 2 read -p "input two str:" first second 3 [ $first == "a" ] && echo "yes" || echo "no" #如果键盘输入的第一个是a,但是此时的输出结果是No,但是如果把a的引号去掉,或者给$first加上引号输出的就是yes
-
默认变量
$0~$n,表示shell脚本的参数,包括shell脚本命令本身,shlle脚本命令本身为$0 $#:#表示最后一个参数的标号。 $@:表$1、$2、$3......
-
shell脚本的条件判断
- shell脚本支持条件判断,虽然可以通过&&和||来实现简单的条件判断,但是稍微复杂一点的场景就不适合了
- shell脚本提供了if then条件判断语句,语法如下:
if 条件判断 ; then //判断成立要做的事情 fi
- 示例如下
1 #!/bin/bash 2 read -p "input first num:" first 3 read -p "input second num:" second 4 if [ $first == $second ]; then 5 echo "==" 6 exit 0 7 elif [ $first -gt $second ]; then 8 echo ">" 9 exit 0 10 else 11 echo "<" 12 fi
-
case选择语句
case $变量 in “第1个变量内容”) 程序段 ;; //表示该程序块结束!! “第2个变量内容”) 程序段;; “第n个变量内容”) 程序段 ;; esac
- 示例如下:
1 #!/bin/bash 2 3 case $1 in 4 "a") 5 echo "param is a" 6 ;; 7 "b") 8 echo "param is b" 9 ;; 10 *) 11 echo "other" 12 ;; 13 esac 14
- $1表示shell命令的第一个参数,第四行只有半个括号,通配符不需要加引号
-
shell函数
- shell支持自建函数,写法如下:
function fname () { //函数代码段 }
- function可写可不写,fname为函数名
1 #!/bin/bash 2 3 print(){ 4 echo "param 1:$1" 5 echo "param 2:$2" 6 } 7 print a b
- 最后一行是给print传递参数
-
shell循环
while [条件] //括号内的状态是判断式 do //循环开始 //循环代码段 done # until do done,表示条件不成立的时候循环,条件成立以后就不循环了 until [条件] do //循环代码段 done
-
for 循环
for var in con1 con2 con3…… do //循环代码段 如果要使用in后面的变量,那么就使用var和python差不多 done # 还有一种for循环和c语言的比较相似 for((初始值; 限制值; 执行步长)) do //循环代码段 done