一、文件描述符
英文是file descriptor簡稱fd。
文件描述符是一個非負整數(shù)。它是一個索引值,指向進程打開的文件。
Linux程序在執(zhí)行任何形式的 I/O 操作時,都是在讀取或者寫入一個文件描述符。
每個文件描述符會與一個打開的文件相對應。
不同的文件描述符也可能指向同一個文件。
在Linux中,每一個進程打開時都會自動獲取3個文件描述符0、1和2,分別表示標準輸入、標準輸出、和標準錯誤,如果要打開其他文件,則文件描述符必須從3開始標識。
文件描述符 | 文件名 | 類型 | 指向硬件 |
---|---|---|---|
0 | /dev/stdin | 標準輸入文件 | 鍵盤 |
1 | /dev/stdout | 標準輸出文件 | 顯示器 |
2 | /dev/stderr | 標準錯誤輸出文件 | 顯示器 |
$ ll /dev/std*
lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Apr 2 07:57 /dev/stdout -> /proc/self/fd/1
$ ll /proc/self/fd/
total 0
lrwx------ 1 root root 64 Apr 6 03:53 0 -> /dev/pts/2
lrwx------ 1 root root 64 Apr 6 03:53 1 -> /dev/pts/2
lrwx------ 1 root root 64 Apr 6 03:53 2 -> /dev/pts/2
lr-x------ 1 root root 64 Apr 6 03:53 3 -> /proc/14038/fd
二、重定向
重定向分為兩種,一種輸入重定向,一種是輸出重定向;
從字面上理解,輸入輸出重定向就是「改變輸入與輸出的方向」的意思??梢园阎囟ㄏ蚶斫鉃橹赶?。
(一)輸出重定向
輸出重定向是指命令的結(jié)果不再輸出到顯示器上,而是輸出到其它地方,一般是文件中。
這樣做的最大好處就是把命令的結(jié)果保存起來,當我們需要的時候可以隨時查詢。
1.標準輸出重定向
command 1>file 以覆蓋的方式,把command的正確輸出結(jié)果輸出到file文件中。
command 1>>file 以追加的方式,把command的正確輸出結(jié)果輸出到file文件中。
2.標準錯誤重定向
command 2>file 以覆蓋的方式,把command的錯誤信息輸出到file文件中。
command 2>>file 以追加的方式,把command的錯誤信息輸出到file文件中。
3.標準輸出與標準錯誤同時重定向
command 1>file1 2>file2 以覆蓋的方式,把正確的輸出結(jié)果輸出到file1文件中,把錯誤信息輸出到file2文件中。
command 1>>file1 2>>file2 以追加的方式,把正確的輸出結(jié)果輸出到file1文件中,把錯誤信息輸出到file2文件中。
command 1>file 2>file 以覆蓋的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。不推薦這種方式。
command 1>>file 2>>file 以追加的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。
注意
(1)輸出重定向的完整寫法是fd>file或者fd>>file,其中fd表示文件描述符,如果不寫,默認為1,也就是標準輸出文件。
當文件描述符為大于1的值時,比如2,就必須寫上。
(2)fd和>之間不能有空格,否則Shell會解析失?。?gt;和file之間的空格可有可無。為了保持一致,我習慣在>兩邊都不加空格。
4./dev/null文件
如果你既不想把命令的輸出結(jié)果保存到文件,也不想把命令的輸出結(jié)果顯示到屏幕上,干擾命令的執(zhí)行,那么可以把命令的所有結(jié)果重定向到/dev/null文件中。
大家可以把 /dev/null 當成Linux 系統(tǒng)的垃圾箱,任何放入垃圾箱的數(shù)據(jù)都會被丟棄,不能恢復。
command 1>/dev/null 2>/dev/null
5.用法舉例
(1)標準輸出重定向
echo 'hello world' >foobar.txt
cat foobar.txt
運行結(jié)果:
hello world
echo 'hello world' >>foobar.txt
cat foobar.txt
運行結(jié)果:
hello world
hello world
(2)標準錯誤重定向
ls foobar 2>err.log
cat err.log
運行結(jié)果:
ls: 無法訪問 'foobar': 沒有那個文件或目錄
(3)標準輸出與標準錯誤同時重定向
ls >out.log 2>err.log
ls foobar >>out.log 2>>err.log
cat out.log
cat err.log
(4)輸出到/dev/null文件
ls foobar >/dev/null 2>/dev/null
(二)輸入重定向
輸入重定向就是改變輸入的方向,不再使用鍵盤作為命令輸入的來源,而是使用文件作為命令的輸入。
命令必須能接受標準輸入作為參數(shù)。
1.標準輸入重定向
command 0<file 將file文件中的內(nèi)容作為command的輸入。
2.here document
格式如下:
command 0<<delimiter
document
delimiter
Here Document是Shell中的一種特殊的重定向方式,將兩個delimiter之間的內(nèi)容document作為輸入。
注意
delimiter可以是任意字符串。
開始的delimiter后面必須是一個換行符。
結(jié)尾的delimiter一定要頂格寫,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 縮進。
3.here string
格式如下:
command 0<<<string 將字符串string作為輸入
cat <<<'hello world'
等同于
echo 'hello world' | cat
注意
輸入重定向的完整寫法是fd<file,其中fd表示文件描述符,如果不寫,默認為0,也就是標準輸入文件。
4.用法舉例
(1)輸入重定向
統(tǒng)計文檔中有多少行文字。
wc -l foobar.txt
2 foobar.txt
wc -l <foobar.txt
2
上面兩個例子的結(jié)果不同:第一個例子,會輸出文件名;第二個不會,因為它僅僅知道從標準輸入讀取內(nèi)容。
(2)逐行讀取文件內(nèi)容。
while read str; do
echo $str
done <foobar.txt
這種寫法叫做代碼塊重定向,也就是把一組命令同時重定向到一個文件。
(3)Here Document
wc -l <<eof
foo
bar
eof
也可以將Here Document用在腳本中,例如:
#!/bin/bash
cat <<eof
foo
bar
eof
(4)here string
批量重命名文件名含有空格的文件
重命名前:
txt 2014.02.14.log
txt 2014.02.15.log
重命名后:
txt_2014_02_14.log
txt_2014_02_15.log
腳本內(nèi)容
oldifs=$IFS
IFS=$'\n'
for file in `ls`;do
mv $file `sed -r 's/[ .]/_/g;s/(.*)_/\1./' <<< $file`
done
IFS=$oldifs
(三)輸入和輸出同時重定向
command 0<file1 1>file2 將file1作為command的輸入,并將command的正確結(jié)果輸出到file2。
(四)文件描述符復制
文件描述符的復制是指將一個文件描述符指向另一個文件描述符指向的文件。使用”&”進行復制。
n<&m:n指向m指向的文件。作為輸入
n>&m:n指向m指向的文件。作為輸出
可以發(fā)現(xiàn)總是前面指向后面,即n指向m。
例如,3>&1表示3指向1指向的文件,1指向的文件是/dev/stdout,3也重定向到/dev/stdout,以后進程將數(shù)據(jù)寫入3的時候,將直接輸出到屏幕。這里的3>&1等價于3>/dev/stdout。如果后面改變了1指向的文件,由于3的目標仍然是/dev/stdout,所以可以拿3來還原1使其目標變回/dev/stdout。
為什么不用n<m與n>m呢?
因為<與>后面必須是文件名,不支持文件描述符。如果使用2>1,它會把1解釋成文件名。所以就有了&,專門用來處理兩個文件描述符的重定向。
command 1>file 2>&1 以覆蓋的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。
command 1>>file 2>&1 以追加的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。
command &>file 以覆蓋的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。
command &>>file 以追加的方式,把正確輸出和錯誤信息同時保存到同一個文件file中。
&>是一種特殊寫法,&>file等價于1>file 2>&1
(五)重定向的執(zhí)行順序
重定向順序很重要:1>file 2>&1和2>&1 1>file是不同的。
1>file 2>&1。這里分兩個過程:先將1重定向到file文件;之后再將2指向1,1此時已經(jīng)重定向到file文件上,因此2也重定向到file。所以,最終的結(jié)果是標準輸出重定向到file,標準錯誤也重定向到file。
2>&1 1>file。這里也分兩個過程:先將2指向1,而此時1重定向的文件是默認的/dev/stdout,所以2也重定向到/dev/stdout;之后再將1重定向到file文件。也就是說,這里的標準錯誤和標準輸出仍然是分開輸出的。所以,最終的結(jié)果是標準錯誤輸出到/dev/stdout,即屏幕上,而標準輸出將輸出到file文件中。文章來源:http://www.zghlxwxcb.cn/news/detail-725377.html
例子:文章來源地址http://www.zghlxwxcb.cn/news/detail-725377.html
ls foobar >foobar.txt 2>&1
ls foobar 2>&1 >foobar.txt
到了這里,關(guān)于Shell輸入輸出重定向的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!