生产力工具:shell 与 Bash 脚本

作者:吴甜甜
个人博客网站: wutiantian.github.io
注意:本文只是我个人总结的学习笔记,不适合0基础人士观看。


参考内容:

王顶老师 linux bash 视频教程

http://billie66.github.io/TLCL/book

C语言编程网: http://c.biancheng.net/shell/

推荐书籍:《UNIX环境编程》,有内容,有远离,课后习题也很棒。


目录

我为什么学 shell

我首先接触到 shell 是在深圳的一家fpga的方案公司参观交流时,看到工程师对fpga进行编程时,敲几个字符就插入了代码块,感觉很快,是生产力的决胜武器。工程师告诉我,每个 fpga 公司都有自己的核心技术专利,编写好的私有库就是通过几个字符的脚本插入到程序中,每家都不同,模块不对外公开。

我意识到,成为具有核心价值的工程师必须掌握这项技能!

我本科时学的是电子信息工程,对软件的态度并没有什么都要会的意识,只是用到再学。但对于 shell ,它并不能迫在眉睫能解决什么必须处理的问题,却成为人与人差距的重要一环之一。

写本内容时,是应用于图像机器学习中遇到实际问题写的个人笔记。当我准备用手头的《Linux程序设计》书时,很失望,看着块头挺大。内容可看的不多。网上的博客大多数内容比较浅,实战性不强。所以我自己写给自己复习。

嵌入式的shell是精简过的,语法略有不同,这点要注意。比如说数组,部分命令的输出和PC尚的存在一定差异。

什么是 shell 与 BASH

  • shell:
    一说到命令行,我们真正指的是 shell。
    shell 就是一个程序,它接受从键盘输入的命令, 然后把命令传递给操作系统去执行。

  • BASH
    “bash” 是 “Bourne Again SHell” 的首字母缩写。
    bash 是由 Steve Bourne 的人写成 shell 程序的增强版

因为基于“命令行”界面,而不是“图形”界面,所以 shell 与 bash 的适应性更强,能应用在多种系统中,是“通杀”的技能。

学 shell 与 BASH 立竿见影的好处

三步编写执行一个 Shell 脚本

命令

命令提示符与命令的概念简述

  • 命令提示符:说明 shell已经准备好输入了

例如: [[email protected] ~]$
表示:当前用户Teenie在主机名为wutiantian.github.io的当前路径为家目录

注意,后续的“定制 shell 环境”章节 有具体更改为自己心中环境的设置过程。

  • 命令行语法

以“空格”分隔,不管几个空格都算一个空格。

例如: ls -l /usr

  • 如何选择命令行发挥更大优势

命令的详细

选项 options 分为 短选项和长选项,功能效果一样

长说明

cd: cd [-L|[-P [-e]] [-@]] [dir]
    Change the shell working directory.

    Change the current directory to DIR.  The default DIR is the value of the
    HOME shell variable.

    The variable CDPATH defines the search path for the directory containing
    DIR.  Alternative directory names in CDPATH are separated by a colon (:).
    A null directory name is the same as the current directory.  If DIR begins
    with a slash (/), then CDPATH is not used.

    If the directory is not found, and the shell option `cdable_vars' is set,
    the word is assumed to be  a variable name.  If that variable has a value,
    its value is used for DIR.

    Options:
        -L  force symbolic links to be followed: resolve symbolic links in
        DIR after processing instances of `..'
        -P  use the physical directory structure without following symbolic
        links: resolve symbolic links in DIR before processing instances
        of `..'
        -e  if the -P option is supplied, and the current working directory
        cannot be determined successfully, exit with a non-zero status
        -@  on systems that support it, present a file with extended attributes
            as a directory containing the file attributes

    The default is to follow symbolic links, as if `-L' were specified.
    `..' is processed by removing the immediately previous pathname component
    back to a slash or the beginning of DIR.

    Exit Status:
    Returns 0 if the directory is changed, and if $PWD is set successfully when
    -P is used; non-zero otherwise.

短说明

bash: cd: --: invalid option
cd: usage: cd [-L|[-P [-e]] [-@]] [dir]

匹配关键字
等价于man -k ls

SSL (3ssl)           - OpenSSL SSL/TLS library
_llseek (2)          - reposition read/write file offset
aconnect (1)         - ALSA sequencer connection manager
add-shell (8)        - add shells to the list of valid login shells
afInitChannels (3)   - initialize audio data format for a track in an audio f...
afOpenFile (3)       - open an audio file and create a file handle structure ...
afs_syscall (2)      - unimplemented system calls
afSetVirtualChannels (3) - set the virtual data format for a track in an audi...
afSetVirtualSampleFormat (3) - set the virtual data format for a track in an ...
alsabat (1)          - command-line sound tester for ALSA sound card driver
alsactl (1)          - advanced controls for ALSA soundcard driver
alsactl_init (7)     - alsa control management - initialization
alsaloop (1)         - command-line PCM loopback
alsamixer (1)        - soundcard mixer for ALSA soundcard driver, with ncurse...
amidi (1)            - read from and write to ALSA RawMIDI ports
amixer (1)           - command-line mixer for ALSA soundcard driver
aplay (1)            - command-line sound recorder and player for ALSA soundc...
...

linux系统基础操作

linux思想:一切皆文件

解析例如:
档案类型权限 连节数 档案拥有者  档案所属群组  文件大小  档案最后被修改时间  档名
-rw-r--r--  1      Teenie       Teenie     3803     6月  24 21:43     .bashrc

文件类型标记方法:
|首位|类型|举例|文件举例|
|---|---|---|---|
|-|普通文件|文本文件、二进制文件|a.c , 1.txt , a.out , test1.sh ,bbbb.txt-hard看不出类型的文本硬链接|
|d|文件夹||cache/|
|l|符号链接文件|后面会用->打印出它指向的文件|ln -s src.c linker.c
linker.c就是src.c的一个符号链接文件
lrwxrwxrwx 1 root root 3 .... linker.c -> src.c|
|s|socket文件||
|p|管道文件|||

  • linux文件存储

至少包括两部分,(1)文件数据本身(2)文件原数据
原数据包括:文件属性(创建时间、修改时间、所有者、权限、文件名)。
这些原数据链接到了数据块本身,所以本身就是一个硬链接
当硬链接数量比1少时,文件就被删除了。

探索操作系统状态

显示系统当前时间和日期
This command displays the current time and date.

2019年 06月 30日 星期日 18:21:15 CST

显示当前月份的日历
A related command is cal which, by default, displays a calendar of the current month.

      六月 2019
日 一 二 三 四 五 六
                   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              

结束终端会话

We can end a terminal session by either closing the terminal emulator window, or by entering the exit command at the shell prompt:

确定文件类型

/home/Teenie/.bashrc: ASCII text

linux文件系统跳转

/home/Teenie
普通用户根目录的工作目录名:在home目录下的该用户名地址下。

切换到当前路径下的Teenie文件夹目录路径下
在几乎所有的情况下,你可以省略”./”。它是隐含的

To change your working directory (where we are standing in our tree-shaped maze) we use the cd command. To do this, type cd followed by the pathname of the desired working directory. A pathname is the route we take along the branches of the tree to get to the directory we want. Pathnames can be specified in one of two different ways; as absolute pathnames or as relative pathnames. Let’s deal with absolute pathnames first.
|路径的两种方式|特征|
|---|---|
|相对路径|用一对特殊符号来表示相对位置:符号 “.” 指的是工作目录,”..” 指的是工作目录的父目录|
|绝对路径|根目录开头的“/”开始,直到它的目的地|

切换到上一级目录

操作文件和目录

附:item 表示文件或目录

将用户账户密码拷贝至当前目录

"/etc/passwd"->"./passwd"
显示操作过程

cp:是否覆盖"./passwd"?

将a与passwd文件,复制到dir1文件夹中

文本处理

文本处理用处:文档、网页、电子邮件、打印输出、程序源代码

  • 排序

打印 hello.c 文本文档中的非打印字符,让人更明了程序排版

#include<stdio.h>$
int main(void)$
{$
    printf("hello world");$
    return 0;$
 } $

sort 程序对标准输入的内容,或命令行中指定的一个或多个文件进行排序,然后把排序 结果发送到标准输出。

使用与 cat 命令相同的技巧,我们能够演示如何用 sort 程序来处理标准输入

sort >foo.txt
c
a
b

Ctrl-d 组合键来表示文件的结尾

cat foo.txt
a
b
c
看到文本行有序地显示

sort 程序能接受命令行中的多个文件作为参数,所以有可能把多个文件合并成一个有序的文件。

例如, 如果我们有三个文本文件,想要把它们合并为一个有序的文件。

查看磁盘中目录,哪个文件夹占用磁盘空间大,数字逆序排列前十个

245984  /usr/share/fonts
122532  /usr/share/icons
114424  /usr/share/doc
89328   /usr/share/help
82640   /usr/share/libreoffice
60556   /usr/share/pyzy
55588   /usr/share/app-install
42228   /usr/share/mythes
41496   /usr/share/fcitx-sogoupinyin
39692   /usr/share/man
  • 切片
  • 比较


cat file1.txt
a
b
c
d

cat file2.txt
b
c
d
e

comm file1.txt file2.txt
a
            b
            c
            d
    e
1特  2特  共有

comm -12 file1.txt file2.txt
b
c
d
隐藏12列

diff file1.txt file2.txt
1d0     如何把file1改成file2.txt?
< a     删除d第一行的a
4a4     把第2个文件的第4行
> e     加上e

diff -c file1.txt file2.txt
context模式
*** file1.txt
--- file2.txt
*************
*** 1,4 *****
-a
 b
 c
 d
--- 1,4 -----
 b
 c
 d
+e

diff -u file1.txt file2.txt
unin 统一模式
---file1.txt
+++file2.txt
@@-1,4,+1,4@@
-a
 b
 c
 d
+e
  • 运行时编辑

The tr program is used to transliterate characters.

tr 程序被用来更改字符。我们可以把它看作是一种基于字符的查找和替换操作。

停止

权限

Linux 系统有多用户性能。

为了使多用户特性付诸实践,那么必须发明一种方法来阻止用户彼此之间受到影响。

毕竟,一个用户的行为不能导致计算机崩溃,也不能乱动属于另一个用户的文件。

在 Unix 术语中,每个人 是指整个世界。可以用 id 命令,来找到关于你自己身份的信息

uid 从1000开始变号

权限的基础组合值
|Octal|Binary|File Mode|
|---|---|---|---|
|1|001|--x|execute|
|2|010|-w-|write|
|4|100|r--|read|
八进制有8种组合,对以上三种进行组合相加赋值即可。

  • 对于脚本文件,有两个常见的权限设置

注意:为了能够执行脚本文件,脚本必须是可读的

chmod gu=rw foo.txt
组权限赋值

chmod o-x foo.txt
减去other组的x可执行功能

chmod 755 foo.txt
把文件的权限设为755

软件安装管理

软件包管理工具:系统中,一种安装和维护软件的方法

如果我们花些时间在 Linux 社区里,我们会看到很多像Linux发行版中哪一个是“最佳”之类的观点。 这些讨论通常非常可笑,集中在一些像桌面背景的漂亮程度(一些人不使用 Ubuntu, 只是因为 Ubuntu 默认主题颜色是棕色的!)和其它的琐碎东西上。

Linux 发行版本质量最重要的决定因素是软件包管理系统和其支持社区的持久性。随着我们 花更多的时间在 Linux 上,我们会发现它的变化是非常快的。大多数一线 Linux 发行版每隔六个月发布一个新版本,并且许多独立的程序每天都会更新。为了能和这些 如暴风雪一般多的软件保持联系,我们需要一些好工具来进行软件包管理。

选择 linux 发行版的重要指标:软件包管理

对于早期 linux 用户,人们需下载和编译源代码来安装软件。
如果有预先编译好的软件包,使用起来相对容易和快速一些

拥有对软件源代码的访问权限是linux的伟大之处,它赋予每个人定制和优化系统权利。

以 ubuntu16为例:

  • 查找安装

命令 子命令 包名
apt install git

apt 命令首先分析 git 依赖关系,这就是包管理的好处.
如果程序发现缺少了一个依赖,则会报错并退出。

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
Suggested packages:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email
  git-gui gitk gitweb git-arch git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,176 kB of archives.
After this operation, 24.1 MB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu xenial-updates/main amd64 git amd64 1:2.7.4-0ubuntu1.6 [3,176 kB]
Fetched 3,176 kB in 3s (878 kB/s)
Selecting previously unselected package git.
(Reading database ... 241828 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.7.4-0ubuntu1.6_amd64.deb ...
Unpacking git (1:2.7.4-0ubuntu1.6) ...
Setting up git (1:2.7.4-0ubuntu1.6) ...
  • 卸载

命令 子命令 包名
apt remove git
y

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  liberror-perl libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
  git git-core
0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
After this operation, 24.1 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 242467 files and directories currently installed.)
Removing git-core (1:2.7.4-0ubuntu1.6) ...
Removing git (1:2.7.4-0ubuntu1.6) ...
  • 更新

apt update 更新源

更新已安装的包
命令 子命令 包名
apt upgrade git

Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version (1:2.7.4-0ubuntu1.6).
Calculating upgrade... Done
The following packages were automatically installed and are no longer required:
  libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
  • 显示包信息

知道包名后,要显示软件包的详细信息,例如:版本号、大小、校验值和软件描述等信息时。

apt-cache show firefox

Package: firefox
Architecture: amd64
Version: 67.0.4+build1-0ubuntu0.16.04.1
Priority: optional
Section: web
Origin: Ubuntu
...

列出所有已经安装的软件包
apt list --installed

Listing... Done
a11y-profile-manager-indicator/xenial,xenial,xenial,now 0.1.10-0ubuntu3 amd64 [installed]
account-plugin-facebook/xenial,xenial,xenial,xenial,xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
...
firefox/xenial-updates,xenial-security,xenial-updates,xenial-security,xenial-security,xenial-updates,now 67.0.4+build1-0ubuntu0.16.04.1 amd64 [installed]
...

PS:aptitude与 apt-get 一样,是 Debian 及其衍生系统中功能极其强大的包管理工具。

与 apt-get 不同的是,aptitude在处理依赖问题上更佳一些。

编译程序make

编译就是把源码(一个由程序员编写的人类可读的程序的说明)翻译成计算机处理器的语言的过程。

ubuntu16 下,编译一个叫做 diction 的程序,来自 GNU 项目。步骤:

(1)安装编译器

安装 ftp 与 gcc 两个文件。

(2)获取源代码

Connected to ftp.gnu.org.
220 GNU FTP server ready.

Name (ftp.gnu.org:root): anonymous


230-NOTICE (Updated October 13 2017):
...
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.


ftp> ls

200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
...
-rw-r--r--    1 0        0            2925 Apr 04 20:15 README
-rw-r--r--    1 0        0          405121 Oct 23  2003 before-2003-08-01.md5sums.asc
-rw-rw-r--    1 0        3003       262986 Jul 05 09:50 find.txt.gz
drwxrwxr-x  320 0        3003        12288 Jun 17 21:54 gnu
drwxrwxr-x    3 0        3003         4096 Mar 10  2011 gnu+linux-distros
-rw-rw-r--    1 0        3003       483088 Jul 05 09:50 ls-lrRt.txt.gz
drwxr-xr-x    3 0        0            4096 Apr 20  2005 mirrors
lrwxrwxrwx    1 0        0              11 Apr 15  2004 non-gnu -> gnu/non-gnu
...
226 Directory send OK.


ftp> cd gnu/dicition

550 Failed to change directory.



ftp> cd gnu/diction

250 Directory successfully changed.


ftp> ls

200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 3003     65534       68940 Aug 28  1998 diction-0.7.tar.gz
-rw-r--r--    1 3003     65534       90957 Mar 04  2002 diction-1.02.tar.gz
-rw-r--r--    1 3003     65534      141062 Sep 17  2007 diction-1.11.tar.gz
-rw-r--r--    1 3003     65534         189 Sep 17  2007 diction-1.11.tar.gz.sig
226 Directory send OK.


ftp> get diction-1.11.tar.gz

local: diction-1.11.tar.gz remote: diction-1.11.tar.gz
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for diction-1.11.tar.gz (141062 bytes).
226 Transfer complete.
141062 bytes received in 1.99 secs (69.1985 kB/s)


ftp> bye

221 Goodbye.
此时根目录下多了个压缩包
diction-1.11.tar.gz

解压缩文件

(3)查看代码

.c与.h文件

(4)编译预处理

执行 configure 预处理文件=>产生 makefile脚本文件

(5)编译程序

执行命令 make 会直接找 makefile=>创建很多 .o 文件

(6)安装程序

(7)查看程序是否安装好

shell眼中看世界——“展开”

当按下 enter 键后,发生在命令行中的一些“魔法”,这种魔法就是展开的过程

字符展开

打印出当前目录下的所有文件夹名,不会显示隐藏文件。

当回车键被按下时,shell 在命令被执行前在命令行上自动展开任何符合条件的字符, 所以 echo 命令的实际参数并不是”*“,而是它展开后的结果。

路径名展开

/usr/kerberos/share  /usr/local/share

通配符所依赖的工作机制叫做路径名展开。

波浪线展开

波浪线字符(“~”)有特殊的含义。

当它用在 一个单词的开头时,它会展开成指定用户的家目录名,如果没有指定用户名,则展开成当前用户的家目录

算术表达式展开

shell 在展开中执行算数表达式。当作计算器来使用。

算术表达式展开使用这种格式:

表达式是指算术表达式,它由数值和算术操作符组成。
注意:美元符号不能丢掉!
例如

算术表达式只支持整数(全部是数字,不带小数点),但是能执行很多不同的操作。

在算术表达式中空格并不重要,并且表达式可以嵌套。例如,5的平方乘以3:
注意:嵌套的$与括号切不可少!否则报错!!!

echo $(($((5**2))*3))
75

echo with $((5%2)) left over.
with 1 left over.

花括号展开

这种模式不能 嵌入空白字符。
花括号展开可以嵌套。

花括号的模式中 创建多个文本字符串。
echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back

echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
使用了一个整数区间

echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
倒序排列的字母区间

echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
花括号展开可以嵌套

参数展开

参数展开特性在 shell 脚本中比直接在命令行中更有用。

存储小块数据,并给每块数据命名的能力有关系。许多像这样的小块数据, 更恰当的称呼应该是变量,可供你方便地检查它们。

"USER"的变量包含你的用户名。可以这样做来调用参数,并查看 USER 中的内容

echo $USER
teenie

查看有效的变量列表
printenv |less

其它展开类型中,如果你误输入一个字符,展开就不会发生

这时 echo 命令只简单地显示误键入的模式。

但在参数展开中,如果你拼写错了一个变量名, 展开仍然会进行,只是展开的结果是一个空字符串。

命令(展开)替换

命令替换允许我们把一个命令的输出作为一个展开模式来使用

ls -l $(which cp)
-rwxr-xr-x 1 root root 151024 3月   3  2017 /bin/cp
把 which cp 的执行结果作为一个参数传递给 ls 命令,因此可以在不知道 cp 命令 完整路径名的情况下得到它的文件属性列表。

file $(ls /usr/bin/* | grep zip)
/usr/bin/funzip:     ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=06412c648a6927c4a14c751fe2412db3425ecd0f, stripped
/usr/bin/gpg-zip:    POSIX shell script, ASCII text executable
...
管道线的输出结果成为 file 命令的参数列表

引用-控制展开

shell 提供了一种叫做引用的机制,来有选择地禁止不需要的展开。

echo this is a    test
this is a test
shell 利用单词分割删除掉 echo 命令的参数列表中多余的空格

echo The total is $100.00
The total is nu00.00

echo The total is $00.00
The total is bash0.00

echo The total is$100.00
The total isnu00.00

因为 1 是没有定义的变量,参数展开把 $1 的值替换为 nu

echo the winner is $smith
the winner is

引用-双引号-限制部分展开

把文本放在双引号中, shell 使用的特殊字符,都失去它们的特殊含义,被当作普通字符来看待

有几个例外: $, (反斜杠),和 `(倒引号)。

这意味着单词分割、路径名展开、 波浪线展开和花括号展开都将失效,然而参数展开、算术展开和命令替换 仍然执行

使用双引号,我们可以处理包含空格的文件名。

比方说我们是不幸的 名为 two words.txt 文件的受害者。
如果我们试图在命令行中使用这个 文件,单词分割机制会导致这个文件名被看作两个独自的参数,而不是所期望 的单个参数:
ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory

使用双引号,我们可以阻止单词分割,得到期望的结果;
进一步,我们甚至可以修复 破损的文件名。

ls -l "two words.txt"
-rw-rw-r-- 1 me   me   18 2008-02-20 13:03 two words.txt
 mv "two words.txt" two_words.txt

记住,在双引号中,参数展开、算术表达式展开和命令替换仍然有效:

echo "$USER$((2+2))"
teenie4

单词分割机制会在单词中寻找空格,制表符,和换行符,并把它们看作 单词之间的界定符。

这意味着无引用的空格,制表符和换行符都不是文本的一部分, 它们只作为分隔符使用。

echo "this is a    test"
this is a    test

单词分割被禁止,内嵌的空格也不会被当作界定符,它们成为参数的一部分。

一旦加上双引号,我们的命令行就包含一个带有一个参数的命令。

单词分割机制把换行符看作界定符,对命令替换产生了一个虽然微妙但有趣的影响
echo $(cal)
六月 2019 日 一 二 三 四 五 六 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

echo "$(cal)"
      六月 2019
日  一 二 三 四  五 六
                   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
命令行只有一个参数,参数中包括嵌入的空格和换行符。

引用-单引号-禁止展开

如果需要禁止所有的展开,我们要使用单引号。以下例子是无引用,双引号,和单引号的比较结果

echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/teenie/*.txt a b foo 4 teenie

echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 teenie

echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER

转义字符

如果没有准确地理解展开模式,shell 总是神秘和混乱的源泉,并且 shell 潜在的能力也 浪费掉了。

只想引用单个字符。
在字符之前加上一个反斜杠,叫做转义字符。
经常在双引号中使用转义字符,来有选择地阻止展开

使用转义字符来消除文件名中一个字符的特殊含义,是很普遍的。
这些字符包括”$”, “!”, “ “等字符。

echo "The balance for user $USER is: \$5.00"
The balance for user teenie is: $5.00
防止美元符号展开

IO 重定向

IO

”I/O”代表输入/输出。标准的输入为键盘,标准的输出为屏幕,而不是保存到磁盘文件。

通过工具,你可以重定向命令的输入输出,命令的输入来自文件,而输出也存到文件

重定向

标准错误重定向没有专用的重定向操作符。为了重定向标准错误,我们必须参考其文件描述符。
|将错误信息输出到文件操作|说明|
|---|---|
|ls -l /bin/usr 2> ls-error.txt|因为标准错误和文件描述符2一样,我们用这种 表示法来重定向标准错误
文件描述符”2”,紧挨着放在重定向操作符之前,来执行重定向标准错误到文件 ls-error.txt 任务。|
|cat ls-error.txt|ls: cannot access '/bin/usr': No such file or directory错误信息已经在所指定文件中|

重定向标准输出和错误到同一个文件
|命令|说明|
|---|---|
|ls -l /bin/usr > ls-output.txt 2>&1|首先重定向标准输出到文件 ls-output.txt,
然后 重定向文件描述符2(标准错误)到文件描述符1(标准输出)使用表示法2>&1。
注意重定向的顺序安排非常重要。标准错误的重定向必须总是出现在标准输出 重定向之后,要不然它不起作用。|

处理不需要的输出/dev/null位存储桶

管道操作符|提取数据

  • 多个命令连接起来组成一个强大的命令管道
    管道操作符”|”(竖杠),一个命令的标准输出可以通过管道送至另一个命令的标准输入
  • 过滤器

管道线经常用来对数据完成复杂的操作。有可能会把几个命令放在一起组成一个管道线。 通常,以这种方式使用的命令被称为过滤器。过滤器接受输入,以某种方式改变它,然后输出它。

比方说我们下载了一个 大型文件,这个文件被分离成多个部分(USENET 中的多媒体文件经常以这种方式分离), 我们想把它们连起来

movie.mpeg.001 movie.mpeg.002 … movie.mpeg.099,we could join them back together with this command

正则表达式

用“元字符”实现复杂匹配

  • 学正则表达式,就是学“元字符”,实现复杂的匹配

  • 正则表达式通配符比较相似,但其规模更庞大。

  • 非常灵活,组合使用方法多

正则表达式可应用在很多命令:grep、find、less、vim...

  • 正则表达式是一种符号表示法,被用来识别文本模式。

元字符和原义字符

grep

global regular expression print

我们能看出 grep 程序和正则表达式有关联。

本质上,grep 程序会在文本文件中查找一个指定的正则表达式,并把匹配行输出到标准输出

regex 是指一个正则表达式。

  • grep 的选项
  • 常用 grep 命令选项

专项专题(选看)

显示与查找文件

  • 常用命令

其实这三个命令除了 cat 命令有合并文件的功能,其余功能上相近,只是从浏览习惯和显示方式上有所不同。

  • 通配符 wildchar

快速指定一组文件名

  • 查找文件
  • 操作符

即使拥有了 find 命令提供的所有测试条件,我们还需要一个更好的方式来描述测试条件之间的逻辑关系

归档 tar、解压、批量

保护数据安全主要方式之一:备份

  • 归档:把多个文件和目录合并成一个大的文件。

归档操作通常和压缩操作配合使用

  • 压缩与解压缩

gzip 程序被用来压缩一个或多个文件。当执行 gzip 命令时,则原始文件的压缩版会替代原始文件

(1)查看需操作文件。拷贝本机的配置文件和目录,包括脚本及用户账号密码等信息
ls -l /etc > foo.txt
ls -lh
-rw-r--r--   1 root root  15K 6月   30 22:40 foo.txt

(2)对文件进行压缩
gzip foo.txt
ll
-rw-r--r--   1 root root   2980 6月  30 22:41 foo.txt.gz

此时容量由15k变为2980,压缩变小了。并且foo.txt文件消失了,增加了红色的foo.txt.gz压缩包

(3)对压缩包进行解压
gunzip foo.txt.gz
ll
-rw-r--r--   1 root root  14907 6月   30 22:43 foo.txt
此时容量由2980变为14907,恢复原大小。并且foo.txt.gz压缩包文件消失了,增加了白色的foo.txt普通文件

简化上面2步骤为

ls -l /etc | gzip > foo.txt.gz
ll
-rw-r--r--   1 root root   2980 6月  30 22:41 foo.txt.gz
  • 打包
(1)归档查看需操作文件。

tar cf playground.tar playground/
ll
drwxrwxr-x 102 teenie teenie   4096 6月  30 20:34 playground/
-rw-r--r--   1 root   root    61440 6月  30 22:45 playground.tar
(2)查看归档下内容
tar tf playground.tar

(3)提取归档
把tar文件释放到foo1文件夹下
mkdir foo1
cd foo1
tar xf ../playground.tar
ll
drwxrwxr-x 102 book book 4096 6月  30 00:34 playground/
(4)归档并压缩
tar czf playground.tgz  playground
  • 常用打包并压缩命令
  • tar 批量问题

我想进行批量解压tar文件,使用tar -xvf .tar会出错,提示“Not found in archive”。

解决方法有很多,比如写一个脚本之类的。

请问为什么tar不支持这种通配符语法呢?是否有特殊的原因? 我试过gzip就支持 gzip -d .tar.gz。

回答:通配符是shell解决的问题。

tar -xvf *.tar实际上执行tar时,tar接收到的展开是 tar -xvf a.tar b.tar c.tar …

如果当前目录跟本没有tar的东西,那么tar就收到’*.tar’这个参数

与win不同,linux所有字符都可以作文件名,也即目录中不存在着 *.tar这个文件

为了防止 *.tar被shell解释为a.tar b.tar c.tar…

可以给它加个单引号。用tar解开一个Archive时,语法是 tar -xvf <tarfile.tar>

<tarfile.tar> 是选项f所要求的,只能是一个文件,比如myfiles.tar。

myfiles.tar所包含的归了档的文件中的一个或者多个成员文件。

  • 远程同步

  • 学习 sync 有什么用?

我感觉用不到,远端可以用git拉取,本地可以拷贝。那么有没有必要了解该指令呢?

我个人觉得指令不重要,重要的是原理。原理需要手动去实现才能更直观掌握。即使在命令行下用不到,但在其他领域,同步的概念仍然会有,例如我在双系统下,使用火狐的同一账号可以同步书签等内容,需要验证的窗口提示“sync”等单词,我看到该单词就立即明白该页内容,而不是一个陌生概念,需要翻译整个页面,还要考虑安全问题。

  • 实例:把playground文件夹下内容同步到foo文件夹下
ls
foo playground

rsync -av playground foo
    显示信息 源文件  目的地
此时,foo文件夹下就有了playground文件夹及其下所有内容
ls foo/
playground

rsync -av playground foo
再执行一遍,没有变化则不会做同步操作
对其中一个文件作更改则只同步那一个文件

内存与进程的性能

  • 查看磁盘剩余空间的数量,disk free

To see the current amount of free space on your disk drives

文件系统        含量          已用    可用    已用%  挂载点
Filesystem     1K-blocks      Used Available Use% Mounted on
udev             3041592         0   3041592   0% /dev
tmpfs             614356     16924    597432   3% /run
/dev/sda1      102049120  11838668  85003620  13% /
tmpfs            3071760       328   3071432   1% /dev/shm
tmpfs               5120         4      5116   1% /run/lock
tmpfs            3071760         0   3071760   0% /sys/fs/cgroup
/dev/sdb1      309505024    280824 293479228   1% /work
vmhgfs-fuse    524289020 292404892 231884128  56% /mnt/hgfs
tmpfs             614356        72    614284   1% /run/user/1000
  • 显示内存剩余空间

To display the amount of free memory.

              total        used        free      shared  buff/cache   available
Mem:        6143524      983732      506060       31860     4653732     4744492
Swap:       1045500           0     1045500
  • 进程

现在的操作系统都支持多任务,意味着操作系统通过在一个执行中的程序和另一个 程序之间快速地切换造成了一种它同时能够做多件事情的假象。Linux 内核通过使用进程来 管理多任务。进程,就是Linux 组织安排正在等待使用 CPU的各种程序的方式。

ps
   PID TTY          TIME CMD
 84009 pts/18   00:00:00 bash
 87162 pts/18   00:00:00 bash
 88998 pts/18   00:00:00 bash
 92203 pts/18   00:00:00 ps

ps x
   PID TTY      STAT   TIME COMMAND
  2163 ?        Ss     0:01 /lib/systemd/systemd --user
  2164 ?        S      0:00 (sd-pam)
  2169 ?        Sl     0:00 /usr/bin/gnome-keyring-daemon --daemonize --login
...

ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0 185312  5800 ?        Ss   6月11   0:12 /sbin/init sp
root          2  0.0  0.0      0     0 ?        S    6月11   0:00 [kthreadd]
...
  • kill杀死进程
top

  PID USER      PR  NI    VIRT    RES    SHR S    %CPU   %MEM  TIME+ COMMAND
92495 teenie      20   0 1992668 265724 135284 S   0.3  4.3   0:29.76 firefox
...

我想关闭火狐浏览器

kill 92495
此时浏览器被关闭

存储媒介-设备挂载

llinux有非常强大得设备管理能力。

物理设备:比如说硬盘,还是网络设备。
虚拟存储设备:像 RAID(独立磁盘冗余阵列)和 LVM(逻辑卷管理器)。

命令行需要手动完成设备挂载

  • 挂载

把设备连接到文件系统树种,允许设备参与操作系统的文件系统中。

网络

Linux 有大量丰富的网络命令,被用来创建各式各样的网络系统和装置, 包括防火墙,路由器,名称服务器,网络连接式存储设备等。

  • 丢包率---衡量通信是否正常的指标

一旦启动,ping 命令会持续在特定的时间间隔内(默认是一秒)发送数据包,直到它被中断

按下组合键 Ctrl-c,中断这个命令之后,ping 打印出运行统计信息

一个正常工作的网络会报告零个数据包丢失

一个成功执行的“ping”命令会意味着网络的各个部件(网卡,电缆,路由,网关) 都处于正常的工作状态。

  • 网络测试

  • 网络正常

PING www.a.shifen.com (182.61.200.6) 56(84) bytes of data.
域名先被解析为IP地址
64 bytes from 182.61.200.6: icmp_seq=1 ttl=51 time=47.5 ms
再由 IP 地址回复消息,每隔1秒返回一个数据包
64 bytes from 182.61.200.6: icmp_seq=2 ttl=51 time=44.5 ms
64 bytes from 182.61.200.6: icmp_seq=3 ttl=51 time=44.5 ms
按 ctrl+c 后,会停止并打印简单报告
...
--- www.a.shifen.com ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7020ms
rtt min/avg/max/mdev = 44.533/45.274/47.577/0.957 ms
  • 网络有问题

随便写了地址,主机不存在的,可能产生 ping 不通的情况

PING 192.168.20.20 (192.168.20.20) 56(84) bytes of data.

--- 192.168.20.20 ping statistics ---
20 packets transmitted, 0 received, 100% packet loss, time 19442ms
  • 测试网络问题的方法步骤

(1)本机 IP 地址测试

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.027 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.053 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.058 ms
^C
--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3064ms
rtt min/avg/max/mdev = 0.027/0.049/0.059/0.013 ms

(2)自己的 IP 地址测试

PING 192.168.31.137 (192.168.31.137) 56(84) bytes of data.
64 bytes from 192.168.31.137: icmp_seq=1 ttl=64 time=0.175 ms
64 bytes from 192.168.31.137: icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from 192.168.31.137: icmp_seq=3 ttl=64 time=0.058 ms
^C
--- 192.168.31.137 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3080ms
rtt min/avg/max/mdev = 0.048/0.085/0.175/0.052 ms

(3)网关测试

PING 192.168.31.1 (192.168.31.1) 56(84) bytes of data.
64 bytes from 192.168.31.1: icmp_seq=1 ttl=64 time=5.32 ms
64 bytes from 192.168.31.1: icmp_seq=2 ttl=64 time=3.21 ms
^C
--- 192.168.31.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 79774ms
rtt min/avg/max/mdev = 3.219/4.274/5.329/1.055 ms

(4)结论

若前3步都是正常的,只有目标主机 ping 不通,则确定本机网络没问题

目标机 192.168.20.20 的主机不存在或者宕机了。

  • 网络统计

打印网卡接口信息

Kernel Interface table
ens33     Link encap:Ethernet  HWaddr 00:0c:29:f8:f3:18
          inet addr:192.168.31.137  Bcast:192.168.31.255  Mask:255.255.255.0
          inet6 addr: fe80::bdc1:5d66:2d85:1808/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1315640 errors:0 dropped:0 overruns:0 frame:0
          TX packets:266354 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:504190955 (504.1 MB)  TX bytes:19535936 (19.5 MB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:184851 errors:0 dropped:0 overruns:0 frame:0
          TX packets:184851 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:9704102 (9.7 MB)  TX bytes:9704102 (9.7 MB)

UP 启用;Down 禁用

  • 打印路由表
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.31.1    0.0.0.0         UG        0 0          0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 ens33
192.168.31.0    0.0.0.0         255.255.255.0   U         0 0          0 ens33

Destination:目的地

192.168.31.0 本机在同一网段地址。

Gateway:网关

不能识别的地址都向网关上发,例如此处的 192.168.31.1 网关地址。网关地址为 0.0.0.0 时,不需要网关转发。

  • ssh

windows可以用Xshell、PuTTY 连接到 linux 系统上。

linux 连接到 linux 系统则用SSH命令本身

例如,我用虚拟机中的 centOS7与ubuntu16命令行交互

ssh [email protected]
[email protected]'s password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.15.0-52-generic x86_64)
...
Last login:Thu Jun 30 22:11:46 2019 from 192.168.31.57

定制 shell

shell环境

  • 如何建立 shell 环境?

当我们登录系统后, bash 程序启动,并且会读取一系列称为启动文件的配置脚本, 这些文件定义了默认的可供所有用户共享的 shell 环境。然后是读取更多位于我们自己家目录中 的启动文件,这些启动文件定义了用户个人的 shell 环境。确切的启动顺序依赖于要运行的 shell 会话 类型。有两种 shell 会话类型:一个是登录 shell 会话,另一个是非登录 shell 会话。

登录 shell 会话会在其中提示用户输入用户名和密码;例如,我们启动一个虚拟控制台会话。

非登录 shell 会话通常当我们在 GUI 下启动终端会话时出现。

*注意:更换环境时,需要拷贝自己需要的环境文件,方便在新环境里自动配置,例如:~/.bashrc

定制 shell 提示符$PS1

我目前的格式为:
[[email protected] ~]$

打印当前PS1变量

echo $PS1
\[email protected]:\w\$

修改为自己定制的 shell 提示符步骤:
(1)打开配置文件,非登录 shell 会话的启动文件。
vi ~/.bashrc
(2)修改命令提示符
PS1='\u:\W$'

保存即可设置为:[当前登陆用户@主机名 当前工作目录的最后部分]$

别名alias-创建你自己的命令

多个命令放在同一行上,命令之间 用”;”分开

cd /usr; ls; cd  三个命令依次执行,分好做间隔<=>alias foo='cd /usr; ls; cd'

注意:若不保存配置到配置文件中,则重启后丢失别名内容

写脚本

注释第一行

  • "!"是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行
#!/usr/bin/bash
  • 井号为单行注释符。

  • 没有多行注释符。

注释提示,去系统的PATH目录中查找。

变量

my_name="jack"
my_name='jack';

变量名和等号之间不能有空格,变量后面不能有;

Shell中的引号和PHP类似,字符串可以用单引号,也可以用双引号

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的(详细见单引号-禁止展开,章节)
  • 单引号字串中不能出现单引号(对单引号使用转义符后也不行

双引号:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

使用变量

对于已经定义过的变量,使用的适合在前面添加$

echo $my_name
echo ${my_name}

变量名外面的花括号是可选的,加不加都行,建议使用第二种形式

声明数组

array_name=(value0 value1 value2 value3)
# 或
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
# 读取数组 ${数组名[下标]}
echo ${array_name[@]}
# 取得数组元素的个数
echo ${#array_name[@]}
# 取得数组单个元素的长度
echo ${#array_name[n]}

表达式

左值    右值
空间  =  值

                赋值的等号两边不能有空格
传参=传值            形参=实参
                判断的等号两边有空格

a=b表示赋值,等号前后无空格

a = b表示判断,等号前后有空格

[ a=b ]中括号内部字符,两边都需要有空格

数学运算

Shell 的数学运算和我们高级语言中的语法完全不一样。

你以为是这么写的:

#!/bin/bash
a=10+5
echo $a

Shell 中把所有东西都当成是一个字符串,所以这里它并不知道我们要它进行数学运算。

实际上在 Shell 中你要进行这样的数学运算,你应该这么写:

#!/bin/bash
a=`expr 10 + 5`
echo $a

你还可以这么写:

#!/bin/bash
let a=10+5
echo $a

我更推荐用下面这种形式:

(( a = 10 + 5 ))
echo $a

将需要运算的内容放在两对中括号里面。因为这种方式更加简洁,并且功能也是最为完整,也是最为接近高级语言的写法。

流程控制-if

  • if

特别需要注意的是 if 后面的表达式,其左右两边都要留有一个空格,这是 Shell 的语法。

a=10
b=20

# if
if [ $a==$b ]
then
  echo "true";
fi

# if-else
if [$a==$b]
then
    echo 'true'
else
    echo 'false'
fi

# if-elseif-else
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

流程控制-循环

#for循环
for loop in 1 2 3 4 5
do
    echo "The value is: ${loop}"
done
# 或
for ((i=0;i<100;i++))
do
    echo "The value is: ${loop}"
done
#while循环
int=0
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
  • for循环
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

for var in item1 item2 ... itemN; do command1; command2… done;

  • 无限循环

  • for (( ; ; ))

  • while

while condition
do
    command
done

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。

int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

语句

脚本习题

  • 解压imagenet2012的标注数据, 数据在/home/studyer/course/第一篇-编程基础/linux基础/作业4 批量解压。
    建立文件夹test1,将压缩包放在下面
for dir in test1/*
do
     if test -f $dir
     then
       brr=$(echo $dir | tr "." "\n")
       brrs=( $brr )
       fileid=${brrs[0]}
       echo $fileid
       mkdir $fileid
       tar -xvf $dir -C $fileid
    fi
done

分析:
批量解包+右击解压Extract Here

for 变量 in 列表

为test1/*路径下的各文件解包,dir变量文件名

do循环

if 判断,如果dir变量文件名 ,是一个普通文件则结果为真,执行then内容

一个文件夹下循环到的可能是文件或文件夹,判断循环到的是不是文件夹

打印提取的dir变量文件名,删除"."与换行符,赋值给brr变量

brrs接收brr变量值

把brrs数组下的名称分次给fileid变量名

打印出每次的fileid变量名

创建fileid变量名的文件夹

进行解x包tar操作,过程中信息v显示在输出屏幕上,每次解包到指定的创建的fileid变量名的文件夹中。

附录:如何查看 man 帮助手册

一、 内容结构(说明书页的格式)

二、 命令语法的形式描述

(1)方括号中的项是可选的
(2)不在方括号或者大括号中的想是必选项
(3)粗体字必须按原样准确键入。这一类可能是命令名、标志和文字字符。
(4)斜体字必须用适当的值代替(不显示斜体字的系统上,通常用下划线代替,就如同变量一般,需要根据自己添加适当的值)
(5)后面接省略号(...)的参数可以多次重复。
(6)如果一个单独的选项和一个参数组合在一起,那么该选项和参数必须同时使用
(7)由|竖线字符分开的两个或多项,表示可以从这个列表中选择一个项。

三、 man 手册的章节

1、Standard commands (标准命令)
2、System calls (系统调用)
3、Library functions (库函数)
4、Special devices (设备说明)
5、File formats (文件格式)
6、Games and toys (游戏和娱乐)
7、Miscellaneous (杂项)
8、Administrative Commands (管理员命令)

四、 命令

查看man 手册的说明

MAN(1)                        Manual pager utils                        MAN(1)

NAME
       man - an interface to the on-line reference manuals

SYNOPSIS
       man  [-C  file]  [-d]  [-D]  [--warnings[=warnings]]  [-R encoding] [-L
       locale] [-m system[,...]] [-M path] [-S list]  [-e  extension]  [-i|-I]
       [--regex|--wildcard]   [--names-only]  [-a]  [-u]  [--no-subpages]  [-P
       pager] [-r prompt] [-7] [-E encoding] [--no-hyphenation] [--no-justifi‐
       cation]  [-p  string]  [-t]  [-T[device]]  [-H[browser]] [-X[dpi]] [-Z]
       [[section] page ...] ...
       man -k [apropos options] regexp ...
       man -K [-w|-W] [-S list] [-i|-I] [--regex] [section] term ...
       man -f [whatis options] page ...
       man -l [-C file] [-d] [-D] [--warnings[=warnings]]  [-R  encoding]  [-L
       locale]  [-P  pager]  [-r  prompt]  [-7] [-E encoding] [-p string] [-t]
       [-T[device]] [-H[browser]] [-X[dpi]] [-Z] file ...
       man -w|-W [-C file] [-d] [-D] page ...
       man -c [-C file] [-d] [-D] page ...
       man [-?V]

查看ls 命令手册的默认第一页

查看ls 命令手册的默认第一页

LS(1)                            User Commands                           LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

DESCRIPTION
       List  information  about  the FILEs (the current directory by default).
       Sort entries alphabetically if none of -cftuvSUX nor --sort  is  speci‐
       fied.

       Mandatory  arguments  to  long  options are mandatory for short options
       too.

       -a, --all
              do not ignore entries starting with .

       -A, --almost-all
              do not list implied . and ..

       --author

用gcc编译器编译程序,查看gcc命令手册第一页

GCC(1)                                GNU                               GCC(1)

NAME
       gcc - GNU project C and C++ compiler

SYNOPSIS
       gcc [-c|-S|-E] [-std=standard]
           [-g] [-pg] [-Olevel]
           [-Wwarn...] [-Wpedantic]
           [-Idir...] [-Ldir...]
           [-Dmacro[=defn]...] [-Umacro]
           [-foption...] [-mmachine-option...]
           [-o outfile] [@file] infile...

       Only the most useful options are listed here; see below for the
       remainder.  g++ accepts mostly the same options as gcc.

DESCRIPTION
       When you invoke GCC, it normally does preprocessing, compilation,
       assembly and linking.  The "overall options" allow you to stop this
       process at an intermediate stage.  For example, the -c option says not
       to run the linker.  Then the output consists of object files output by
       the assembler.

查看系统调用open 的man 手册说明

OPEN(2)                    Linux Programmer's Manual                   OPEN(2)

NAME
       open, openat, creat - open and possibly create a file

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

       int openat(int dirfd, const char *pathname, int flags);
       int openat(int dirfd, const char *pathname, int flags, mode_t mode);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       openat():
           Since glibc 2.10:
               _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L

五、 使用范例

附录:学习方法

命令行与指令紧密结合,大量的命令需要记忆。想要快速得掌握,背诵和看资料是没有用的,脑子记忆不深刻,必须练习犯错才能使得脑得到异常信号来加强记忆。把A文件移动到B文件夹下,方式有很多种,选择你认为简单的那种熟练操作就好。大多数的初学者,错误都在拼写,和脑子思考深度无关。熟练了之后,再进行操作则像肌肉般,不过大脑就已经敲出代码,解决问题。

前期只有通过大量的练习,才能在复杂情况下有老司机般应急处理能力。若是连敲错一个字母这类低级语法错误的提示语句都不能立即判断出故障原因,那就不要想着处理高级任务。

主动给自己出题。出题意图、考察点、任务目标,自己先过一遍。

我本科期间学了一门《微机原理与接口技术》课程非常好。起步就是八大指令 MOV 的汇编跳转,后面的内容则是定时器完成40行的小程序。很多同学败在了起步,虽然只有八大指令,但指令限制导致组合很多,移动跳转都不会更无法进行后续程序编写。书上题目并不多,有的甚至因为排版是错的答案,大多数人就放弃了。而我就不同,我会在图书馆找几本同类书对比作补充。虽然每本书都有可能错一部分内容,但不可能所有书的所有题目都是错的。题目做的对不对,自己心里是有数的,几本书即使错也不会错法完全相同,所以发现错并跳过错题还是有谱的。实在没有题目时,我会自己出题,更有目标感去钻研,不会还可以上网查。通过一定数量的训练,找出规律,得出自己的正确模型进而掌握该知识。切忌停止脚步!

  • 关于学习资料的选择

特别是初学编程者,敲代码的行数少于1万行,学习顺序“与任务目标一致视频>专门该领域书本>散乱的博客”>瞎学。

要解决的任务比较灵活,无法直接抄,或者拿来主义却完全看不懂甚至还需要做裁剪时,往往稍微翻书的三脚猫功夫是不能应付的,如果有分值,大概要70分以上。

初学者对编程思想领悟力很弱,很多地方考虑不周全,学了却有很多遗漏,应付不来任务。此时理解概念通过人讲授效果最好。至于看谁的视频,没有非得某一个人不可的说法,找前3个有名的、有趣方便记忆的、成体系、周边练习配套完善的,新的能用的上的(这是我学习考研政治的学法类比出来的)。认真学习一套,远比比较评价 N 套视频有效果。每个讲师其实都有各自优点,只有虔诚认真深入地掌握才能达到好的效果。

初学者书读得太快,合上书可能等于没读。太厚的书容易陷入其中,迷茫,导致章节分配时间没有规划,处处是重点草木皆兵,最后放弃。

非初学者,对该知识有所涉猎,此时时间为王。当书很厚,只缘身在此山中时,微博或 书的PPT 都能尽快拎得清主线,抓住重点,重点地方各个击破,快速阅读与仔细阅读结合。之后再有针对性地看某几节的视频。

关于视频,是人的经验总结。里面只要有一句话对你有用,那么就足够了。这句话往往是核心思想之一,有的是自己总结的,这是初学者巧妇难为无米之炊,脑子里的独创性。有的书中有却没注意的,往往需要看第二遍以后才发现,这时候已经花费很多时间,看视频旧能节省时间。例如,王顶老师在视频里提及的:图形让简单的任务更简单,命令行让复杂的任务成为可能。简单的两句比看多少条的优点罗列明了。

关于好书,总是要读上几遍的,温故知新,不羞耻。

附录:鸣谢

鸣谢王顶老师(河北经贸大学老师)!

因为我要写脚本完成批量处理的任务,所以我在腾讯课堂上观看了他的课程。网上也有其他教程,例如老男孩的运维视频节数百节之多,真心没时间看,而且与我需要的内容并不是完全重合。王顶老师的视频是13小时,39课时,长度适中,有一半课程是可以试看,我看了几节感觉独创的成语穿插知识点容易理解记忆,于是就学了下去,用QQ积分免费兑换总价15元课程,没花钱学了课程。线下我 QQ 向王顶老师请教关于脚本的学习,老师推荐我用他 github仓库上的几个脚本仓库源文件来分析练习,并在网上找了一些理论素材给我做补充。王顶老师一直以来都是有问必答,回复及时。有些与课程无关的技术问题,王老师尽最大可能把知道的知识告诉我,帮助我。因为有他,我在跨领域的学习勇敢学习应用提升自己技能与效率。感谢良师益友的陪伴!

07-08 02:14