=======================================================================================
声明:本人还是个菜鸟,刚接触Linux没有多久,因为本人学习过程中比较爱钻NJJ(可能是有点强迫症),所以总想着获得MAX技,写这个系列的博客是为了总结所学以及方便日后查询。
以下内容都来自书籍或网络,本人只是将它们整合在我的博客中,如果日后有学习到的新技巧还会继续分享出来。啊哈!话有点多了,那么现在就开始吧......
=======================================================================================
6. I/O重定向与文件描述符
I/O重定向:是由shell读取或捕捉来自文件、命令、程序或脚本中的输出,作为输入或输出信息,传递给另外一个文件、命令、程序或脚本。
文件描述符:是Linux内核为了高效管理已被打开的文件所创建的索引,是一个非负整数,从0开始编号。
常用的I/O重定向符:
> 输出重定向符,将命令的输出数据重定向并写入到指定的文件。
(若文件不存大则新建,若文件已存在则原有的内容会被清除后再写入,当noclobber标志被设置时)
(开启noclobber功能:set -o noclobber ,不进行覆盖且提示 ; 关闭noclobber功能:set +o noclobber 覆盖且不提示)
>> 作用与 '>' 类似,不同的是,若文件已存在则以附加的形式把输出的数据写入到文件的最后。
< 将让符号左边的命令直接读取某个文件而不是从键盘(标准输入)输入数据。
重定向符的其它用法:
>| filename 强制覆盖,即使开启了noclobber功能就会进行覆盖操作。
&> filename 把标准输出(1)和标准错误输出(2)均重定向到指定的文件中。
i>& j 把文件描述符 i 表示的输出文件重定向到文件描述符 j 表示的文件。( i 和 j 都是表示文件描述符的数字)
<<[-]word 以指定的标志字符串word之后的here文档作为标准输入,用来模拟人工输入方式,用于here文档脚本中。
(从word之后逐行读取数据,直到遇到第二个word或EOF标志处结束)
(如果 '<<' 后面附带减号 '-' ,则shell将会忽略随后每个文本行中前面的制表符)
例子: $ echo "hello world!" > /tmp/msg.txt (创建一个msg.txt文件并写入"hello world!")
$ wc -m < /tmp/msg.txt (统计msg.txt文件中的字符个数)
说明:
a. 文件描述符 0(标准输入,对应键盘), 1(标准输出,对应屏幕), 2(标准错误输出,一般也对应屏幕), 是在Linux启动过程中,由第一个进程init打开的,而之后创建的新进程都是init进程的直接或间接子进程。
b. 因为创建新进程时会自动继承父进程的打开文件描述符,所以Linux中的所有进程默认都能访问以上3个文件,即能从键盘中接收输入以及能往屏幕输出。
c. 每一个文件描述符都会与一个打开的文件相对应,同时,不同的文件描述符也可能会指向相同的一个文件;相同的文件可以被不同的进程打开,也可以在同一个进程中被多次打开。
d. Linuxt系统会为每一个进程维护一个文件描述符表,该表的值都是从0开始编号的,所以在不同的进程中可能看到相同的文件描述符,此时,它们可能指向同一文件或不同文件,需根据内核维护的三个数据结构具体分析:进程级的文件描述符表,系统级的打开文件表,文件系统中的i-node表。
文件描述符、打开文件表和i-node表之间的关系:
实试结果:(here文档的使用)
7. 管道符 " | " 与三通管道 " | tee "
管道符:是一种特殊的 I/O 重定向,可以把一个命令的标准输出连接到另一个命令的标准输入。
三通管道: 是管道符结合tee程序实现 当标准输入接收并显示数据的同时把数据存储到指定的文件中。例如:
$ ls /usr | wc -w (用于获知 /usr 目录下的文件以及文件夹的总数量,不包括隐藏文件或文件夹)
$ ps -ef | grep cron | grep -v 'grep' | gawk '{print $2}' (用于获知 cron 进程的进程ID号)
$ who | tee /tmp/userlist.txt (将who命令执行的结果输出到屏幕,并保存在 /tmp/userlist.txt 文件中)
T型三通管道功能图:
8. 驯服调皮的文件名
文件命名规则:Linux中除了 " / " 之外,构成文件或文件夹名称的字符可以是任何字符。
(包括:空格符、"@#$&()-"等特殊字符和不可打印字符)
不可打印字符:是指该字符没有与之相对应的可视化字符矩阵信息,即不能在屏幕上输出,该类字符一般用于表示某种功能。
(如:^N 表示 ctrl+N ,按 ctrl+v+n 可在终端输入^N不可打印字符)
隐藏文件或文件夹:Linux系统中,以点号 (.) 开始的文件或文件夹表示带有隐藏属性,要显示它们须通过 ls 的 -a 选项。
(其中单独的点号 "." 还表示当前目录,两个点号 ".." 表示上一级目录)
a. 如果 test/ 目录下除了-abc/ 文件夹外没有其它内容(或有其它内容但不重要可以删除),则可以执行:$ rm /tmp/test/* -rf
(或执行:$ rm /tmp/test -rf ,连同test/目录一起删除掉)
b. 如果只想删除 -abc/ 文件夹,则可执行:$ rm -rf-- -abc ,rm 后面的 "--" 是选项的结束标识,表示在它之后的都是参数了。
(或执行:$ rm ./-abc -rf ,通过点号引用当前目录从而避免直接将 -abc 当成参数)
c. 万能的办法,通过信息节点号来索引文件:$ ls -ai ,列出所有文件或文件夹的信息节点号,输出 " 800168 -abc " 。
(接着执行:$ find . -inum 800168 | xargs -I {} rm {} -rf )
实试结果:
9. 命令历史之 fc 和 history 命令
命令历史机制:Shell的命令历史机制和编辑功能使用户能够重复利用先前输入的命令,以提高用户的交互访问能力。
(命令历史机制主要是由Shell提供的内部命令和环境变量实现的)
(命令历史机制仅适用于交互式Shell,不能在非交互式Shell中使用,如Shell脚本中不能用)
FC命令:a.语法格式1:fc [ -e ename ] [ -nlr ] [ first [ last ] ]
(表示从用户输入的命令历史缓冲区或指定文件中选择指定范围 first~last 的命令)
(-e 选项用于指定编辑器并进入编辑模式,-n 选项用于列出命令时不显示序号)
(-l 选项用于列出命令,-r 选项表示由近至远反向输出)
(first 和 last 即可以是当前命令的序号;也可以是用于匹配每个命令起始的字符串)
例子:
$ fc -l 10 20 (列出命令历史缓冲区或指定文件中序号从10~20的命令)
$ fc -l -10 (列出最近出入的10条命令)
$ fc -l cat (列出最近输入的以cat为起始字符串的命令)
$ fc -e vim 10 20 (使用vim编辑序号从10~20的命令,退出编辑器后执行所有命令)
b. 语法格式2:fc -s [ old=new ] [ command ]
(如果存在"old=new"形式的字符串等号左右不能有空格,则由Shell直接执行命令行替换,然后重新执行编辑后的新命令)
(old 表示命令中存在的字符串,new表示要替换old的新字符串)
(command 参数可以是命令序号,也可以是命令的名称)
例子:
$ fc -s (再次执行上次执行的命令)
$ fc -s 10 (再次执行序号为10的命令)
$ fc -s cat (再次执行最近一条以cat开头的命令)
$ fc -s src=lib ls (再次执行最近一条以ls开头的命令,并将命令中的src替换成lib)
HISTORY命令:
a. HISTSIZE 变量指定命令历史文件的大小,用于限定当前会话期间需要保存到命令历史文件中的命令数量默认值为 500。
b. HISTFILESIZE 变量指定命令历史文件的大小,用于限定不同会话之间需要保存到命令历史文件中的命令数量,也为500。
c. HISTFILE 变量用于指定命令历史文件,默认文件为:$HOME/.bash_history 。
(每当用户退出登录或显示执行 "history -w" 命令时,会将命令历史缓冲区中的内容写入到由HISTFILE指定的文件中)
例子:
$ history (列出缓冲区中部分或全部执行过的命令,取决于shell的版本)
$ history 10 (只列出缓冲区中最近10条命令)
$ history -c (清除命令历史缓冲区中的命令)
$ history -w (将当前缓冲区中的命令历史记录写入到由HISTFILE变量指定的文件中)
实试结果:10. 引用命令历史中的命令之 " ! "
感叹号:在bash中,为了引用命令历史缓冲区或文件中的命令,可利用 " !" 。
常规用法详解:(注意:方括号不是命令的一部分,只表示某些情况下可以省略)
! 表示引用命令历史中的命令,一般不单独使用,当后面不紧跟着空格、换行符、等号 ' = ' 或左括号 ' ( ' 等字符时。
!! 重复执行上一条命令,相当于执行 " !-1 "命令。
!N 重复执行命令历史中序号为N的命令。
!-N 重复执行从当前命令位置开始倒数第N条命令。
!string 重复执行最近一次以string为起始字符串的命令。
!?string[?] 重复执行最近一次包含给定字符串string的命令。
(不附加内容时最后一个 ? 可以省略,但当要附加内容时必须加上)
用法扩展:
a. 以上用法还支持附加内容(一般是命令参数或选项参数)的格式,格式如下所示:
!! append 、!N append 、 !-N append 、 !string append 、 !?string? append
b.以上用法还支持字符串替换功能(替换的内容可以是命令中的任何部分),格式如下所示:
!!:[g]s/old/new[/ append] 、 !N:[g]s/old/new[/ append] 、 !-N:[g]s/old/new[/ append] ;
!string:[g]s/old/new[/ append] 、 !?string?:[g]s/old/new[/ string]
c.字符串替换功能可以接连多个一起使用(注意 ': ' 前后不能有空格),以 !! 为例格式如下所示:
!!:[g]s/old/new/:[g]s/old/new[/ append]
d.引用此次输入命令过程中已经录入的字符串,可使用:!#。e.引用命令历史中上一条命令的参数,可分别使用:!^ (引用首个参数) 、!$ (引用最后一个参数) 、!* (引用所有参数) 。
(可指定命令历史序号,从而引用指定命令的参数:引用第N条{!N^ 、!N$ 、!N* },引用前N条{!-N^ 、!-N$ 、!-N* } )
(使用快捷键引用上一条命令的参数:最后一个参数{ [ ALT +.] 、[ ALT +. ] } ,任意一个参数{ [ ALT +
(使用快捷键时[ ALT +
f. 一种比较简便的引用加替换方式:^old^new^ 。
(重复执行上一条命令,执行前用new字符串替换命令中首次匹配的old字符串,只匹配一次,相当于去掉g的:s/old/new/)
实试结果:
——————————————— 未 完 待 续 —————————————————