Linux重定向
重定向能够实现Linux命令的输入输出与文件之间重定向,以及实现将多个命令组合起来实现更加强大的命令。这部分涉及到的比较多的命令主要有:
- cat:连接文件
- sort:排序文本行
- uniq:忽略或者报告重复行
- wc:统计文件的行数、词数、字节数
- grep:打印匹配制定模式的行
- head:输出文件的头部
- tail:输出文件的尾部
- tee:从标准输入读,并往标准输出或者文件写
1.重定向标准输出
使用>可以将本来出现在屏幕的标准输出信息重定向到一个文件中。我们需要将某个目录下所有文件及目录的列表保存在一个文本文件中:
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一个不存在的目录,并且重定向到文本文件中:
jerry@ubuntu:~$ ls -l /usr/notexist > ls.txt ls: cannot access /usr/notexist: No such file or directory
这时我们看到错误信息。再看看文件ls.txt,我们会发现:
jerry@ubuntu:~$ ls -l ls.txt -rw-r--r-- 1 jerry jerry 0 2012-12-15 22:22 ls.txt
我们可以看到,这个文件中没有任何内容。一方面,ls以及很多Linux命令的错误信息会打印到标准输出文件中,而这里的内容是不会被>操作符重定向到文件中的。另一方面,我们看到,之前在ls.txt文件中的内容也没了,也就是说>操作符是会覆盖原有内容的。
使用>>可以在实现重定向时不覆盖原有内容,而是在文件末尾追加内容。我们可以看一下例子:
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分别代表标准输入、标准输出、标准错误。要将标准错误信息重定向到文件中,可以如下操作:
jerry@ubuntu:~$ ls /usr/notexist 2>lserr.txt jerry@ubuntu:~$ cat lserr.txt ls: cannot access /usr/notexist: No such file or directory
如果要同时将标准输出和标准错误信息同时输出到文件中,则需要如下操作:
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中,还可以有另一种办法如下:
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,可以接受输入信息但是什么都不做。因此要抑制命令的输出信息,只需要如下操作:
ls /usr/ > /dev/null
4.重定向标准输入
cat命令可以接受一组文件为参数,将这些文件复制到标准输出。我们前面的例子中已经多次使用到cat命令来将文本文件的内容读取到屏幕上。cat还有一个很重要的功能:接受一组文件,然后通过重定向将他们重新组合到一个文件中。我们看一个例子:
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会重定向标准输入到标准输出。我们看一个例子:
jerry@ubuntu:~$ cat aaaaaaaaaaa aaaaaaaaaaa bbbbbbbbbbbbbb bbbbbbbbbbbbbb
在这个例子中,键入一行文本,按下回车键之后,刚才输入的内容会立刻显示到屏幕,因此我们看到每两行文本都是一样的。当然我们可以使用<来表示输入重定向。我们要想将文件内容重定向到输出,可以使用cat < file,只是这种方式不如直接cat file来得直接。
5.管道
Linux提供|操作符,该操作符可以将一个命令的输出作为另一个命令的输入,这样通过多个命令的协作来完成一些比较复杂的内容。比如,我们可以通过uniq命令来排除重复的行。但是uniq命令往往需要和sort命令配合使用。因为uniq接收一组排好序的文本,而刚好sort可以将文本行排序。我们看下面的例子:
jerry@ubuntu:~$ cat ls aaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaaaaaaaa jerry@ubuntu:~$ cat ls | sort | uniq aaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbb
我们还可以对uniq命令加上-d选项来查看重复的行,如下:
jerry@ubuntu:~$ cat ls | sort | uniq -d aaaaaaaaaaaaaaaaaaaaaaaa
使用wc命令可以统计文本的行数、单词书和字节数。可以和例如ls命令的输出一起组成管道命令:
jerry@ubuntu:~$ ls /bin /usr/bin/ | sort | uniq | wc 764 763 6347
如果仅仅想要统计行数,只需要在wc命令后面添加-l选项即可。wc命令常用来统计代码的行数。
find cn/ -name "*.php" |xargs cat|wc -l
上面这个例子统计了cn目录下所有php文件的行数之和。
grep命令用来查找匹配的模式,并且打印包含该模式的行。举个例子:
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选项,表示显示的行数。看例子:
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,实时显示出新添加到文件末尾的行数。这样一旦有新的行追加到日志文件的末尾,就会被实时显示在后面。
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命令,它可以接收标准输入的内容并且同时将内容重定向到标准输出以及一个或者多个文件中,直接看例子:
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
save me from myself