重定向能夠實現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