转自:http://www.cnblogs.com/wawlian/archive/2012/12/16/2820351.html
重定向能够实现Linux命令的输入输出与文件之间重定向,以及实现将多个命令组合起来实现更加强大的命令。这部分涉及到的比较多的命令主要有:
1.重定向标准输出
使用>可以将本来出现在屏幕的标准输出信息重定向到一个文件中。我们需要将某个目录下所有文件及目录的列表保存在一个文本文件中:
1
2
3
4
5
6
7
8
9
10
11
12
|
jerry@ubuntu:~$ ls -l /usr/ > ls .txt
jerry@ubuntu:~$ cat ls .txt
total 64
drwxr-xr-x 2 root root 20480 2012-12-08 17:33 bin
drwxr-xr-x 2 root root 4096 2012-02-03 17:21 games
drwxr-xr-x 37 root root 4096 2012-12-08 17:33 include
drwxr-xr-x 58 root root 20480 2012-12-08 17:33 lib
lrwxrwxrwx 1 root root 3 2012-12-08 01:29 lib64 -> lib
drwxr-xr-x 11 root root 4096 2012-12-08 02:38 local
drwxr-xr-x 2 root root 4096 2012-12-08 02:25 sbin
drwxr-xr-x 106 root root 4096 2012-12-08 02:18 share
drwxrwsr-x 4 root src 4096 2012-12-08 01:33 src
|
现在我们ls一个不存在的目录,并且重定向到文本文件中:
1
2
|
jerry@ubuntu:~$ ls -l /usr/notexist > ls.txt
ls: cannot access /usr/notexist: No such file or directory
|
这时我们看到错误信息。再看看文件ls.txt,我们会发现:
1
2
|
jerry@ubuntu:~$ ls -l ls .txt
-rw-r--r-- 1 jerry jerry 0 2012-12-15 22:22 ls .txt
|
我们可以看到,这个文件中没有任何内容。一方面,ls以及很多Linux命令的错误信息会打印到标准输出文件中,而这里的内容是不会被>操作符重定向到文件中的。另一方面,我们看到,之前在ls.txt文件中的内容也没了,也就是说>操作符是会覆盖原有内容的。
使用>>可以在实现重定向时不覆盖原有内容,而是在文件末尾追加内容。我们可以看一下例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
jerry@ubuntu:~$ ls -l /usr/ >> ls .txt
jerry@ubuntu:~$ ls -l /usr/ >> ls .txt
jerry@ubuntu:~$ cat ls .txt
total 64
drwxr-xr-x 2 root root 20480 2012-12-08 17:33 bin
drwxr-xr-x 2 root root 4096 2012-02-03 17:21 games
drwxr-xr-x 37 root root 4096 2012-12-08 17:33 include
drwxr-xr-x 58 root root 20480 2012-12-08 17:33 lib
lrwxrwxrwx 1 root root 3 2012-12-08 01:29 lib64 -> lib
drwxr-xr-x 11 root root 4096 2012-12-08 02:38 local
drwxr-xr-x 2 root root 4096 2012-12-08 02:25 sbin
drwxr-xr-x 106 root root 4096 2012-12-08 02:18 share
drwxrwsr-x 4 root src 4096 2012-12-08 01:33 src
total 64
drwxr-xr-x 2 root root 20480 2012-12-08 17:33 bin
drwxr-xr-x 2 root root 4096 2012-02-03 17:21 games
drwxr-xr-x 37 root root 4096 2012-12-08 17:33 include
drwxr-xr-x 58 root root 20480 2012-12-08 17:33 lib
lrwxrwxrwx 1 root root 3 2012-12-08 01:29 lib64 -> lib
drwxr-xr-x 11 root root 4096 2012-12-08 02:38 local
drwxr-xr-x 2 root root 4096 2012-12-08 02:25 sbin
drwxr-xr-x 106 root root 4096 2012-12-08 02:18 share
drwxrwsr-x 4 root src 4096 2012-12-08 01:33 src
|
2.重定向标准错误信息到文件
没有单纯的一个操作符可以将标准错误信息重定向到文件中。要实现这一点有两种办法。第一种使用文件描述符,在shell中,默认用数字0,1,2分别代表标准输入、标准输出、标准错误。要将标准错误信息重定向到文件中,可以如下操作:
1
2
3
|
jerry@ubuntu:~$ ls /usr/notexist 2>lserr.txt
jerry@ubuntu:~$ cat lserr.txt
ls : cannot access /usr/notexist : No such file or directory
|
如果要同时将标准输出和标准错误信息同时输出到文件中,则需要如下操作:
1
2
3
|
jerry@ubuntu:~$ ls -l /usr/notexist > lsboth.txt 2>&1
jerry@ubuntu:~$ cat lsboth.txt
ls : cannot access /usr/notexist : No such file or directory
|
在比较新的shell中,还可以有另一种办法如下:
1
2
3
|
jerry@ubuntu:~$ ls -l /usr/notexist &> lsboth.txt
jerry@ubuntu:~$ cat lsboth.txt
ls : cannot access /usr/notexist : No such file or directory
|
3.屏蔽不想看到的信息
Linux中有一个特殊的文件/dev/null,这个文件叫做bit bucket,可以接受输入信息但是什么都不做。因此要抑制命令的输出信息,只需要如下操作:
1
|
ls /usr/ > /dev/null
|
4.重定向标准输入
cat命令可以接受一组文件为参数,将这些文件复制到标准输出。我们前面的例子中已经多次使用到cat命令来将文本文件的内容读取到屏幕上。cat还有一个很重要的功能:接受一组文件,然后通过重定向将他们重新组合到一个文件中。我们看一个例子:
1
2
3
4
5
6
7
8
|
jerry@ubuntu:~$ cat ls1
aaaaaaaaaaaaaaaaaaaaaaaa
jerry@ubuntu:~$ cat ls2
bbbbbbbbbbbbbbbbbbbbbbbb
jerry@ubuntu:~$ cat ls1 ls2 > ls
jerry@ubuntu:~$ cat ls
aaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbb
|
cat ls1 ls2 > ls这个命令将ls1和ls2文件中的内容合并到ls文件中了。cat命令的这种功能不仅仅适用于文本文件,同样对二进制文件有效。这个场景主要在将多个压缩包文件合并到一个压缩包中用到。
cat也可以不传递参数,这种情况下,cat会重定向标准输入到标准输出。我们看一个例子:
1
2
3
4
5
|
jerry@ubuntu:~$ cat
aaaaaaaaaaa
aaaaaaaaaaa
bbbbbbbbbbbbbb
bbbbbbbbbbbbbb
|
在这个例子中,键入一行文本,按下回车键之后,刚才输入的内容会立刻显示到屏幕,因此我们看到每两行文本都是一样的。当然我们可以使用<来表示输入重定向。我们要想将文件内容重定向到输出,可以使用cat < file,只是这种方式不如直接cat file来得直接。
5.管道
Linux提供|操作符,该操作符可以将一个命令的输出作为另一个命令的输入,这样通过多个命令的协作来完成一些比较复杂的内容。比如,我们可以通过uniq命令来排除重复的行。但是uniq命令往往需要和sort命令配合使用。因为uniq接收一组排好序的文本,而刚好sort可以将文本行排序。我们看下面的例子:
1
2
3
4
5
6
7
|
jerry@ubuntu:~$ cat ls
aaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaa
jerry@ubuntu:~$ cat ls | sort | uniq
aaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbb
|
我们还可以对uniq命令加上-d选项来查看重复的行,如下:
1
2
|
jerry@ubuntu:~$ cat ls | sort | uniq -d
aaaaaaaaaaaaaaaaaaaaaaaa
|
使用wc命令可以统计文本的行数、单词书和字节数。可以和例如ls命令的输出一起组成管道命令:
1
2
|
jerry@ubuntu:~$ ls /bin /usr/bin/ | sort | uniq | wc
764 763 6347
|
如果仅仅想要统计行数,只需要在wc命令后面添加-l选项即可。wc命令常用来统计代码的行数。
1
|
find cn/ -name "*.php" | xargs cat | wc -l
|
上面这个例子统计了cn目录下所有php文件的行数之和。
grep命令用来查找匹配的模式,并且打印包含该模式的行。举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
jerry@ubuntu:~$ ls /bin /usr/bin/ | sort | uniq | grep zip
bunzip2
bzip2
bzip2recover
funzip
gpg-zip
gunzip
gzip
unzip
unzipsfx
zipgrep
zipinfo
|
在这个例子中,zip就是一个模式,表示包含字符串zip。我们在/bin和/usr/bin目录下找出名字带有zip的程序,并且打印这些程序的名字。grep命令可以使用正则表达式,功能也非常强大,这里我们不侧重介绍。
head和tail命令也常常用于组成管道命令。head可以查看文件或者文本的前面部分。tail查看文件或者文本的末尾部分。二者都可以接收-n选项,表示显示的行数。看例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
jerry@ubuntu:~$ ls /bin/ | head -n 5
bash
bunzip2
busybox
bzcat
bzcmp
jerry@ubuntu:~$ ls /bin/ | tail -n 5
zforce
zgrep
zless
zmore
znew
|
tail还有一个重要的用处,就是实时显示某些程序的日志文件。tail能接受一个选项-f,实时显示出新添加到文件末尾的行数。这样一旦有新的行追加到日志文件的末尾,就会被实时显示在后面。
1
2
|
jerry@ubuntu:~$ tail -f /var/log/messages
Dec 16 06:40:20 ubuntu rsyslogd: [origin software= "rsyslogd" swVersion= "4.2.0" x-pid= "533" x-info= "http://www.rsyslog.com" ] rsyslogd was HUPed, type 'lightweight' .
|
最后再介绍一个tee命令,它可以接收标准输入的内容并且同时将内容重定向到标准输出以及一个或者多个文件中,直接看例子:
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
jerry@ubuntu:~$ ls /bin/ | tee tee .txt | grep zip
bunzip2
bzip2
bzip2recover
gunzip
gzip
jerry@ubuntu:~$ cat tee .txt
bash
bunzip2
busybox
bzcat
bzcmp
bzdiff
bzegrep
bzexe
bzfgrep
bzgrep
bzip2
bzip2recover
bzless
bzmore
cat
checkpassword
chgrp
chmod
chown
chvt
cp
cpio
dash
date
dd
df
dir
dmesg
dnsdomainname
domainname
dumpkeys
echo
ed
egrep
false
fgconsole
fgetty-login
fgetty-login2
fgrep
fuser
fusermount
grep
gunzip
gzexe
gzip
hostname
ip
kbd_mode
kill
less
lessecho
lessfile
lesskey
lesspipe
ln
loadkeys
login
ls
lsmod
mkdir
mknod
mktemp
more
mount
mountpoint
mt
mt-gnu
mv
nano
nc
nc.openbsd
netcat
netstat
nisdomainname
ntfs-3g
ntfs-3g.probe
ntfs-3g.secaudit
ntfs-3g.usermap
open
openvt
pidof
ping
ping6
plymouth
ps
pwd
rbash
readlink
rm
rmdir
rnano
run-parts
sed
setfont
setupcon
sh
sh.distrib
sleep
static-sh
stty
su
sync
tailf
tar
tempfile
touch
true
ulockmgr_server
umount
uname
uncompress
unicode_start
vdir
which
ypdomainname
zcat
zcmp
zdiff
zegrep
zfgrep
zforce
zgrep
zless
zmore
znew
|
参考书:
《The Linux Command Line》 William E. Shotts, JR. no starch press
1重定向
1.1 重定向符号
> 输出重定向到一个文件或设备 覆盖原来的文件
>! 输出重定向到一个文件或设备 强制覆盖原来的文件
>> 输出重定向到一个文件或设备 追加原来的文件
< 输入重定向到一个程序
1.2标准错误重定向符号
2> 将一个标准错误输出重定向到一个文件或设备 覆盖原来的文件 b-shell
2>> 将一个标准错误输出重定向到一个文件或设备 追加到原来的文件
2>&1 将一个标准错误输出重定向到标准输出 注释:1 可能就是代表 标准输出
>& 将一个标准错误输出重定向到一个文件或设备 覆盖原来的文件 c-shell
|& 将一个标准错误 管道 输送 到另一个命令作为输入
1.3命令重导向示例
在 bash 命令执行的过程中,主要有三种输出入的状况,分别是:
1. 标准输入;代码为 0 ;或称为 stdin ;使用的方式为 <
2. 标准输出:代码为 1 ;或称为 stdout;使用的方式为 1>
3. 错误输出:代码为 2 ;或称为 stderr;使用的方式为 2>
[test @test test]# ls -al > list.txt
将显示的结果输出到 list.txt 文件中,若该文件以存在则予以取代!
[test @test test]# ls -al >> list.txt
将显示的结果累加到 list.txt 文件中,该文件为累加的,旧数据保留!
[test @test test]# ls -al 1> list.txt 2> list.err
将显示的数据,正确的输出到 list.txt 错误的数据输出到 list.err
[test @test test]# ls -al 1> list.txt 2> &1
将显示的数据,不论正确或错误均输出到 list.txt 当中!错误与正确文件输出到同一个文件中,则必须以上面的方法来写!不能写成其它格式!
[test @test test]# ls -al 1> list.txt 2> /dev/null
将显示的数据,正确的输出到 list.txt 错误的数据则予以丢弃! /dev/null ,可以说成是黑洞装置。为空,即不保存。
1.4为何要使用命令输出重导向
• 当屏幕输出的信息很重要,而且我们需要将他存下来的时候;
• 背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
• 一些系统的例行命令(例如写在 /etc/crontab 中的文件)的执行结果,希望他可以存下来时;
• 一些执行命令,我们已经知道他可能的错误讯息,所以想以『 2> /dev/null 』将他丢掉时;
• 错误讯息与正确讯息需要分别输出时。
2 管线命令 ( pipe )
就如同前面所说的, bash 命令执行的时候有输出的数据会出现,那么如果这群数据必需要经过几道手续之后才能得到我们所想要的格式,应该如何来设定?这就牵涉到管线命令的问题了( pipe ),管线命令使用的是『 | 』。
例子:简单的管线命令
假设我们要读取 last 这个指令中,那个 root 登入的『次数』应该怎么作?
那么我所进行的步骤是:
1. 执行 last ,将所有这个月的所有人登入数据取出来;
2. 使用 grep 将上面的输出数据(stdout)当中的 root 撷取出来,其它的不要;
3. 使用 wc 这个可以计算行数的指令将上一步的数据计算行数!
由于 last 的输出是一行代表一次登入,所以只要计算几行就代表登入几次的意思,经由上面三个步骤,将 last 数据逐步的筛选,就可以得到我们的数据了!整个命令可以写成如下: [test @test bin]# last | grep root | wc -l
这个管线命令『 | 』仅能处理经由前面一个指令传来的正确信息,也就是standard output ( STDOUT ) 的信息,对于 stdandard error 并没有直接处理的能力。
2.1基本的管线命令指令介绍
• cut
语法:[root @test /root ]# cut -d "分隔字符" [-cf] fields
参数说明:
-d :后面接的是用来分隔的字符,预设是『空格符』
-c :后面接的是『第几个字符』
-f :后面接的是第几个区块?
范例:[root @test /root]# cat /etc/passwd | cut -d ":" -f 1
将 passwd 这个文件里面,每一行里头的 : 用来作为分隔号,而列出第一个区块!也就是姓名所在啦!
[root @test /root]# last | cut -c1-20
将 last 之后的数据,每一行的 1-20 个字符取出来!
• sort
语法:[root @test /root ]# sort [-t 分隔符] [(+起始)(-结束)] [-nru]
参数说明:
-t 分隔符:使用分隔符来隔开不同区间,预设是 tab
+start -end:由第 start 区间排序到 end 区间
-n :使用『纯数字』排序(否则就会以文字型态来排序)
-r :反向排序
-u :相同出现的一行,只列出一次!
范例:[root @test /root]# cat /etc/passwd | sort将列出来的个人账号排序!
[root @test /root]# cat /etc/passwd | sort -t: +2n将个人账号中,以使用者 ID 来排序(以 : 来分隔,第三个为 ID ,但第一个代号为 0 之故)
[root @test /root]# cat /etc/passwd | sort -t: +2nr反相排序啰!
• wc
语法:[root @test /root ]# wc [-lmw]
参数说明:
-l :多少行
-m :多少字符
-w :多少字
范例:[root @test /root]# cat /etc/passwd | wc -l这个文件里头有多少行?
[root @test /root]# cat /etc/passwd | wc -w这个文件里头有多少字!?
• uniq这个指令用来将『重复的行删除掉只显示一个』
语法:[root @test /root ]# uniq
范例:[root @test /root]# last | cut -d" " -f1 | sort | uniq
• tee命令重定向到文件的同时将数据显示在屏幕上
语法:[root @test /root ]# last | tee last.list | cut -d " " -f1
范例:[root @test /root]# last | tee last.list | cut -d " " -f1
• tr
语法:[root @test /root ]# tr [-ds] SET1
参数说明:
-d :删除 SET1 这个字符串
-s :取代掉重复的字符!
范例:[root @test /root]# last | tr '[a-z]' '[A-Z]' <==将小写改成大写
[root @test /root]# cat /etc/passwd | tr -d : <== : 这个符号在 /etc/passwd 中不见了!
[root @test /root]# cat /home/test/dostxt | tr -d '\r' > dostxt-noM
• split
语法:[root @test /root ]# split [-bl] 输入文件 输出文件前导字符
参数说明:
-b :以文件 size 来分
-l :以行数来分
范例:[root @test /root]# split -l 5 /etc/passwd test <==会产生 testaa, testab, testac... 等等的文件
说明:在 Linux 底下就简单的多了!你要将文件分割的话,那么就使用 -b size 来将一个分割的文件限制其大小,如果是行数的话,那么就使用 -l line 来分割!
管线命令在 bash 的连续的处理程序中是相当重要的!另外,在 log file 的分析当中也是相当重要的一环。
管道输送到一个命令的标准输入可以使用标准输入参数”-“ 进行更仔细的控制.如cat命令的示例
eg: sort mylist | more
sort mylist | cat –n | lpr
pwd | cat – mylist | lpr
摘自:http://hi.baidu.com/suchshow/blog/item/972286fb6467ae1a6d22eb9e.html