https://www.linuxidc.com/Linux/2019-03/157335.htm
以下來自一個重度linux使用患者不請自來的回答。
shell程序中 2> /dev/null 代表什么意思?答:“2> /dev/null” 代表忽略掉錯誤提示信息。
如題 2> 代表什么意思?講錯誤輸出刪除?答:“2>” 代表重定向操作錯誤提示信息。只有這兩個字符並不能刪除錯誤輸出。
如果有正確的輸出並賦值給i,i會得到正確的值嗎?
答:i會得到正確的值。
上面的三個回答是我認為相對比較友好,容易理解的回答。
---------------------------------------我是啰哩啰唆回答的分割線-------------------------------------
2016-12-12 更新錯誤描述與更新排版
下面,咱們一起來看看這個命令操作涉及到的知識點(敲黑板。。。。)題主問題里描述的這條命令其實涉及到三部分的內容,如下圖:
(原諒我奇怪的畫風……)
下面的所有回到都是假設大家對linux沒有太多的了解所作的,如有高手,打臉的時候請輕一點。+_+
1. 文件描述符
下面手打一段《linux shell腳本攻略》的描述(如有侵權我會刪除的 T_T):
文件描述符是與文件輸入、輸出關聯的整數。它們用來跟蹤已打開的文件。最常見的文件描述符是stidin、stdout、和stderr。我們可以將某個文件描述符的內容重定向到另外一個文件描述符中。
《linux shell腳本攻略》
文件描述符我們常見的就是系統預留的0,1和2這三個,他們的意義分別有如下對應關系:
- 0 —— stdin(標准輸入)
- 1 —— stdout (標准輸出)
- 2 —— stderr (標准錯誤)
其中,shell編程里經常用到的就是描述符1,和描述符2。這樣下面我們來舉兩個栗子,就知道神馬是1和2了:
1 —— stdout
假設:在當前目錄下我們“有且只有”一個文件名為 123.txt 的文本文件。這個時候我們運行下面的命令【ls 123.txt】:
我們就會獲得一個標准輸出stdout的輸出結果“123.txt” 。
2 —— stderr
按照上面同樣的假設,我們運行另外一跳命令【ls abc.txt】:
我們就會獲得一個標准錯誤stderr的輸出結果“ls:無法訪問abc.txt:沒有那個文件或目錄”。
有同學應該會覺得,這兩個事例好像跟1和2這兩個阿拉伯數字好像沒有關系。這個就要結合第二個知識點“重定向操作”來理解了。
2.重定向操作
書里找不到准確的關於重定向的描述,我很不要臉滴來說一下我的理解吧。重定向操作,其實就是通過在shell命令后面追加一個重定向操作符號,將shell命令對應的文件描述符輸出的文本信息重新輸入到另外一個指定文件的操作。
重定向操作符號有兩個>和>>。盡管這兩個操作符都可以將重定向到文件,但是前者會先清空文件,再寫入內容;后者會將內容追加到現有文件的尾部。(對了,重定向的操作制定的文件如果原來不存在的話,重定向的操作會主動創建這個文件名的文件的)
下面我們結合第1個知識點文件描述符來舉栗子吧。
重定向標准輸出stdout
如上圖所示,對比沒有添加重定向的操作,ls命令在使用之后並沒有將字符“123.txt”這個字符串打印到屏幕上。在緊接着的cat操作之后,我們可以看到本來應該輸出字符串被記錄在了stdout.txt這個文件里面了。
其實,對於標准輸出的重定向操作,>等同於1>。上面栗子執行命令【ls 123.txt > stdout.txt】得到的效果也是一樣的。
重定向標准錯誤stderr
如上圖所示,文件描述符2,標准錯誤的重定向也是同樣的原理被記錄在了文件stderr.txt這個文件里面了。
描述符的重定向還有下面的幾種用法:
你可以將stderr單獨定向到一個文件,將stdout重定向到另一個文件:
cmd 2>stderr.txt 1>stdout.txt
也可以利用下面的方法,將stderr轉換成stdout,使得stderr和stdout都被重新定向到同一個文件中:
cmd> output.txt 2>&1
或者采用這個方法(這個經常用到,我個人比較喜歡用這個,少寫幾個字符(*^__^*) )
cmd &> output.txt
cmd >& output.txt # 兩個表達式效果一樣噠~
(終於最后一個知識點,原來認真答題碼字這么嘞。摔~)
3. linux特殊文件
手抄一段《linux shell腳本攻略》描述:
/dev/null是一個特殊的設備文件,這個文件接收到的任何數據都會被丟棄。因此,null這個設備通常也被成為位桶(bit bucket)或黑洞。
簡單地理解就是,重定向操作給這個/dev/null文件的所有東西都會被丟棄。
因為這些文件描述符輸出的字符串,總是會顯示出來的。如果我們在shell編程的時候,操作到某一條命令的返回結果,我們不想要這個時候又不想讓這個輸出結果打印到屏幕上(打印錯誤,多不好看對不對^_^)我們就可以重定向到/dev/null這個文件來,由/dev/null這個文件負責處理后事。
這個丟棄的結果又不能粗暴的認為是刪除錯誤輸出,這個操作是一個丟棄重定向輸入輸出的操作。
形象地理解就是,ATM機打印的紙質流水賬單(stdout和stderr)本來應該你來保存處理的,但是你又沒有用放在手里(打印屏幕)又礙事,所以賬單從你的手里重新被丟到了垃圾桶(/dev/null)了。但是,垃圾桶的垃圾是怎么處理的你是不知道的。
不知道上面的描述,答主是不是能明白這三個知識點了?只要理解了上面的三個點,其實答主的第三個問題很好滴能解決了。
問題3的思路
讓一個變量獲得命令輸出的結果,是下面這樣的處理:
i=$(ls 123.txt)
這樣,i 就能獲得命令【ls 123.txt】輸出的標准輸出。錯誤提示(標准錯誤)依然會打印到屏幕上顯示。(萬分感謝 @張超 同學在評論中指正的我的錯誤^_^)
針對答主的問題,應該是如下操作:
i=$(ls 123.txt 2> /dev/null)
這樣的命令,ls命令如果出現了錯誤提示,就會被重定向到/dev/null垃圾桶去了。所以,屏幕上不會打印任何輸出關於錯誤的提示字符。在這個命令的操作中,i 獲得文件stdout標准輸出,也就是文件述符1的屏幕輸出結果"123.txt"。
如果,這個123.txt文件不存在,i 就肯定什么都拿不到,因為錯誤提示被/dev/null 吃了(划掉),被重定向丟棄了屏幕也不顯示錯誤提示。所以,i 就是個什么都沒有的空變量。基本就是如下效果一樣:
i=''