I/O

标准输入

一旦登陆 系统就设置一个标准输入(从键盘) 标准输出和标准错误到屏幕

如果想将输出写入文件中

>覆盖写入

用 " > "符号,如: sort nums > file 这是覆盖写入 如果文件不存在就创建 如果存在就覆盖

>>追加写入

用 “>>” ,如: sort nums >> file 追加写入 如果不存在就创建 存在就追加

小技巧

如果 不想直接用“>”覆盖 可以设置**变量“**noclobber”让覆盖写入变成 “>|”,可以防止误触

set -o noclobber 则生效

写入 /root/.bashrc 中永远生效

从文件中读入数据

<读入

< file 将file文件输出到某个指令或sort </etc/passwd 将密码排序后输出到屏幕中

可以同时读入和写入

sort < rawdata >reportrawdata 读入到sort 再将 sort 的结果 写入到report

但读入文件和保存文件不能同一个,否则文件内容清空

因为,保存时按覆盖保存,先将文件"A"清空,再将文件"A"(空的)复制到文件"A"中

sort 命令是原生的 可以对文件内容排序 按数值或字母

标准输出

有两种输出 shell 分为方便用户使用 可以将两种输出分开

stand out && stand error

sort 1 > res_out 代表输出正确结果 和 默认 sort > res_out 一样

sort 2 > res_error 输出错误结果

sort 2 >> res_error追加写入错误结果

1
sort 0 < res` 就是 stand in 默认用 `sort < res

“2>&1“同时写入正确&错误信息

sort 1 >res 2>&1 表示将 正常输出到文件res 中 将错误信息也输出到res中

sort >res 2>&1等同效果

sort >> res 2>&1追加写入

sort &> res 也表示同时写入 正确和错误输出

举例

  • ls Chap_15.txt b > res

b文件不存在,将只会看到 Chap_15的文件消息(只有正确信息

  • ls Chap_15.txt b &> res

则 res有Chap_15文件信息和b文件不存在的错误信息

  • ls Chap_15.txt b >res 2 >error

则分开写入到正确、错误信息

使用>的例子

文件名” PEOPLE “包含一些联系人信息

现在,如果文件包含"Hello" ,就将文件排序

1
grep hello people && sort people > res

grep “查看内容” “文件名”成功执行后再执行 排序 再将结果写入res

SubSHell

子shell && 父shell

当shell 执行一个程序时, shell 是父程序 被执行程序是子程序

父shell 等着子shell 死亡后 再夺回控制权

如:在登陆后的shell 中输入 bash 则进入了子shell ,父shell 开始等待

子shell将继承父shell 的环境,但不会回传出父shell 任何信息,而且不会对父shell 造成影响

相当于是个虚拟机

/dev/null 是个垃圾箱

如果只要看正常输出,不要错误输出 update 2> /dev/null

Piplines 管道符

功能:

  • 将命令的标准输出给另一个命令的标准输入
1
cat file1 file2 | grep hello | wc - l

在文件1、2里面找“hello”统计行数

  • 但Pipline只将前面的标准输出作为后面的**“标准输入”,不能实现参数传递**

举例:

cat 命令可以接收文件名作为参数,执行后会显示出文件的内容。但是 cat 命令不能直接从标准输入接收参数,正如下面的例子:

1
2
3
4
5
6
7
#cat后面直接指定china.txt参数, 可以展示china.txt文件的内容
[roc@roclinux ~]$ cat china.txt
hello beijing

#我们尝试通过标准输入把参数传给cat, 结果却只是显示了文件名而已
[roc@roclinux ~]$ echo china.txt | cat
china.txt
  • 但可以用 xargs实现传递参数

xargs 传递参数

  • execute arguments的缩写

功能:

  • xargs 会将前一个命令的标准输出转换成命令参数。

举例:

1
2
[roc@roclinux ~]$ echo china.txt | xargs cat
hello beijing
  • xargs 的标准输入中出现的“换行符、空格、制表符”都将被空格取代。下面来看一个带有换行符的例子:

空格取代换行符

1
2
3
4
5
6
7
8
[roc@roclinux ~]$ echo -e "china.txt\njapan.txt"
china.txt
japan.txt

#可见, 换行符和空格的作用一样
[roc@roclinux ~]$ echo -e "china.txt\njapan.txt" | xargs cat
hello beijing
hello tokyo
  • 当命令参数中包含了空格时,情况就会复杂很多,一起来看一个示例。

参数中包含了空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#我们创建了3个日志文件, 且故意让文件名称中都含有空格
[roc@roclinux ~]$ for((i=0;i<3;i++)); do touch "test ${i}.log";done

#我们列出创建的文件
[roc@roclinux ~]$ ls -1F
test 0.log
test 1.log
test 2.log

#我们来运行xargs命令, 发现报错了
#-print 指定分隔符 默认为\n
[roc@roclinux ~]$ find . -name '*.log' -print | xargs rm
rm: cannot remove ‘./test’: No such file or directory
rm: cannot remove ‘1.log’: No such file or directory

我们在当前目录中创建了 3 个文件,文件名中间都含有空格。

但当 find 命令获取到的文件名经过 xargs 传送给 rm 命令时,文件“./test 1.log”就变成了“./test”和“1.log”两个文件了。

即原本 3 个文件名刹那间就变成了 6 个文件名,而这 6 个文件其实并不存在,从而引发了错误。

原因

  • 这个错误的根源就在于 xargs 默认的分隔符是空格,如果我们能将 xargs 的分隔符改成其他符号,问题就迎刃而解了!

解决

  • xargs 提供了-0选项,允许将 NULL 作为分隔符
  • find 命令提供的对应方法是 -print0 选项产生以 NULL 字符作为分隔符的输出

在文件名之后输出 NULL,而不像 -print 选项那样输出换行符(换行符会被 xargs 替换成空格)。

1
2
root@lthero:videos$ find . -name '*.log' -print0
./test 1.log./test 0.log./test 2.log

于是,使用下命令,可以找出包含空格的文件并删除

1
find . -name '*.log' -print0 | xargs -0 rm

Tee

tee 可以读一个标准输入同时复制到标准输出文件中

1
cat file1 file2 | tee file3 | grep hello

cat 读取 file1 file2文件 并给tee 保存在file3中,并输出到标准输出,grep又从标准输出收到信息,再搜索"hello"

1
cat file1 file2 file3 | tee file4 file5

将1\2\3的文件合并后复制到4、5中而且内容一样

默认下 如果文件不在,tee可以创建,存在就覆盖写入

tee -a 可以追加写入