shell輸出的那個垃圾桶——/dev/null

昨晚花費一整晚在知乎回答了一個關於shell裏面的重定向輸出到/dev/null的問題。果斷今晚也同步發在這裏,反正也沒人看~~~~linux



如下來自一個重度linux使用患者不請自來的回答。

先用簡單的語言回答題主的問題:
shell

shell程序中 2> /dev/null 表明什麼意思?

答:「2> /dev/null」 表明忽略掉錯誤提示信息。
編程

如題 2> 表明什麼意思?講錯誤輸出刪除?

答:「2>」 表明重定向操做錯誤提示信息。只有這兩個字符並不能刪除錯誤輸出。
ide

若是有正確的輸出並賦值給i,i會獲得正確的值嗎?

答:i會獲得正確的值。

上面的三個回答是我認爲相對比較友好,容易理解的回答。


---------------------------------------我是囉哩囉唆回答的分割線-------------------------------------


  下面,我們一塊兒來看看這個命令操做涉及到的知識點(敲黑板。。。。)題主問題裏描述的這條命令其實涉及到三部分的內容,以下圖:
3d

<img src="https://pic1.zhimg.com/v2-32b909c43d75fa9c1f7c9286fdbffdc4_b.png" data-rawwidth="247" data-rawheight="175" class="content_p_w_picpath" width="247"> v2-32b909c43d75fa9c1f7c9286fdbffdc4_b.pn (原諒我奇怪的畫風……)
  下面的全部回到都是假設你們對linux沒有太多的瞭解所做的,若有高手,打臉的時候請輕一點。+_+


1. 文件描述符
  下面手打一段《linux shell腳本攻略》的描述(若有侵權我會刪除的 T_T):
blog

文件描述符是與文件輸入、輸出關聯的整數。它們用來跟蹤已打開的文件。最多見的文件描述符是stidin、stdout、和stderr。咱們能夠將某個文件描述符的內容重定向到另一個文件描述符中。
                                                                                       《linux shell腳本攻略》


文件描述符咱們常見的就是系統預留的0,1和2這三個,他們的意義分別有以下對應關係:
字符串

  • 0 —— stdin(標準輸入)
    cmd

  • 1 —— stdout (標準輸出)
    同步

  • 2 —— stderr (標準錯誤)it


  其中,shell編程裏常常用到的就是描述符1,和描述符2。這樣下面咱們來舉兩個栗子,就知道神馬是1和2了:
1 —— stdout
  假設:在當前目錄下咱們「有且只有」一個文件名爲 123.txt 的文本文件。這個時候咱們運行下面的命令【ls 123.txt】:

<img src="https://pic4.zhimg.com/v2-8830db673e8054c3050bc47f3d083c73_b.png" data-rawwidth="622" data-rawheight="158" class="origin_p_w_picpath zh-lightbox-thumb" width="622" data-original="https://pic4.zhimg.com/v2-8830db673e8054c3050bc47f3d083c73_r.png">咱們就會得到一個 v2-8830db673e8054c3050bc47f3d083c73_b.pn  咱們就會得到一個 標準輸出stdout的輸出結果「123.txt」 。
2 —— stdout
  按照上面一樣的假設,咱們運行另一跳命令【ls abc.txt】:
<img src="https://pic1.zhimg.com/v2-32eebce74f8dbe4f8ea6c1a3cee4684c_b.png" data-rawwidth="608" data-rawheight="112" class="origin_p_w_picpath zh-lightbox-thumb" width="608" data-original="https://pic1.zhimg.com/v2-32eebce74f8dbe4f8ea6c1a3cee4684c_r.png">咱們就會得到一個 v2-32eebce74f8dbe4f8ea6c1a3cee4684c_b.pn  咱們就會得到一個 標準錯誤stderr的輸出結果「ls:沒法訪問abc.txt:沒有那個文件或目錄」
有同窗應該會以爲,這兩個事例好像跟1和2這兩個阿拉伯數字好像沒有關係。這個就要結合第二個知識點「重定向操做」來理解了。
2.重定向操做
  書裏找不到準確的關於重定向的描述,我很不要臉滴來講一下個人理解吧。重定向操做,其實就是經過在shell命令後面追加一個重定向操做符號,將shell命令對應的文件描述符輸出的文本信息從新輸入到另一個指定文件的操做。
  重定向操做符號有兩個>和>>。儘管這兩個操做符均可以將重定向到文件,可是前者會先清空文件,再寫入內容;後者會將內容追加到現有文件的尾部。 (對了,重定向的操做制定的文件若是原來不存在的話,重定向的操做會主動建立這個文件名的文件的)
  下面咱們結合第1個知識點文件描述符來舉栗子吧。
重定向標準輸出stdout
<img src="https://pic2.zhimg.com/v2-344ea7a024ecd442d39ab9f6e68ff0ad_b.png" data-rawwidth="557" data-rawheight="136" class="origin_p_w_picpath zh-lightbox-thumb" width="557" data-original="https://pic2.zhimg.com/v2-344ea7a024ecd442d39ab9f6e68ff0ad_r.png">如上圖所示,對比沒有添加劇定向的操做,ls命令在使用以後並無將字符「123.txt」這個字符串打印到屏幕上。在緊接着的cat操做以後,咱們能夠看到原本應該輸出字符串被記錄在了stdout.txt這個文件裏面了。 v2-344ea7a024ecd442d39ab9f6e68ff0ad_b.pn  如上圖所示,對比沒有添加劇定向的操做,ls命令在使用以後並無將字符「123.txt」這個字符串打印到屏幕上。在緊接着的cat操做以後,咱們能夠看到原本應該輸出字符串被記錄在了stdout.txt這個文件裏面了。
  其實,對於標準輸出的重定向操做,>等同於1>。上面栗子執行命令【ls 123.txt > stdout.txt】獲得的效果也是同樣的。
重定向標準錯誤stderr
<img src="https://pic3.zhimg.com/v2-cf091eefd7ca4eca5dc44dc8ba5bf8ee_b.png" data-rawwidth="545" data-rawheight="134" class="origin_p_w_picpath zh-lightbox-thumb" width="545" data-original="https://pic3.zhimg.com/v2-cf091eefd7ca4eca5dc44dc8ba5bf8ee_r.png">如上圖所示,文件描述符2,標準錯誤的重定向也是一樣的原理被記錄在了文件stderr.txt這個文件裏面了。 v2-cf091eefd7ca4eca5dc44dc8ba5bf8ee_b.pn  如上圖所示,文件描述符2,標準錯誤的重定向也是一樣的原理被記錄在了文件stderr.txt這個文件裏面了。


描述符的重定向還有下面的幾種用法:
你能夠將stderr單獨定向到一個文件,將stdout重定向到另外一個文件:

cmd 2>stderr.txt 1>stdout.txt

也能夠利用下面的方法,將stderr轉換成stdout,使得stderr和stdout都被從新丁香到同一個文件中:

cmd> output.txt 2>&1

或者採用這個方法(這個常常用到,我我的比較喜歡用這個,少寫幾個字符(*^__^*) )

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】輸出在屏幕的全部結果了。不管輸出的是stdout輸出仍是stderr的錯誤提示。i 這個變量都能獲取到一個字符串。
針對答主的問題,應該是以下操做:

i=$(ls 123.txt 2> /dev/null)

  這樣的命令,ls命令若是出現了錯誤提示,就會被重定向到/dev/null垃圾桶去了。因此,i 這個變量就獲取不到stderr標準錯誤的提示字符串了。因此,在這個命令的操做中,i 就只能得到文件stdout標準輸出,也就是文件述符1的屏幕輸出結果"123.txt"。
  若是,這個123.txt文件不存在,i 就什麼都拿不到,由於錯誤提示被/dev/null 吃了(劃掉),被重定向丟棄了。因此,i 就是個什麼都沒有的空變量。基本就是以下效果同樣:

i=''
相關文章
相關標籤/搜索