Shell 命令通常有輸入輸出。預設從標準輸入裝置(stdin)獲取輸入,結果輸出到標準輸出裝置(stdout)顯示。通常:

  • 標準輸入裝置:鍵盤
  • 標準輸出裝置:終端,即顯示器

Shell 命令執行時都會開啟三個檔案:

  • 標準輸入檔案(stdin):檔案描述符0,從stdin讀取資料
  • 標準輸出檔案(stdout):檔案描述符1,向stdout輸出資料
  • 標準錯誤檔案(stderr):檔案描述符2,向stderr流中寫入錯誤資訊

但是輸入輸出也可來自其它地方,這就是輸入輸出重定向。

1 輸出重定向

1.1 標準輸出重定向

將命令的標準輸出寫到檔案裡:

command 1> log_a.txt # 直接输出,覆盖之前的文件
command 1>> log_b.txt # 添加到之前文件的后面

需要注意command後面的1>1>>,在1>>>之間是沒有空格的。如果按照下面寫法,則1command的參數。

command 1 > log_a.txt

由於預設是標準輸出,也可以去掉1

command > log_a.txt
command >> log_a.txt

1.2 標準錯誤重定向

標準錯誤的檔案描述符是2

command 2>log_a.txt
command 2>>log_a.txt

標準錯誤中的2一定要放置在>或者>>前,且中間沒有空格

1.3 同時重定向

command >log.txt 2>&1 # 把标准错误和标准输出同时输出到一个文件
command 1>log_a.txt 2>log_b.txt # 将两者输出到不同的文件

輸出檔案合併

n >& m # 将输出文件 m 和 n 合并。

1.4 特殊的/dev/null

/dev/null是一個特殊的檔案,寫入到它的內容都會被丟棄;如果嘗試從該檔案讀取內容,那麼什麼也讀不到。(看起來像個黑洞。)但/dev/null檔案非常有用,將命令的輸出重定向到它,會起到禁止輸出的效果。

command > /dev/null
command 2> /dev/null
command > /dev/null 2>&1

2 輸入重定向

可以理解和輸出重定向相反,輸入來自於檔案。

2.1 輸入重定向

標準輸入是鍵盤,其實也可以從檔案輸入:

shell_command < filea.txt # 将filea.txt的内容作为标准输入

2.2 輸入檔案合併

n <& m #将输入文件 m 和 n 合并。

2.3 Here document

就是在命令列中輸入多行文字:

command << delimiter
document
delimiter

它將兩個delimiter之間的內容(document) 作為輸入傳遞給 command

  • 結尾的delimiter一定要頂格寫,前面不能有任何字元,後面也不能有任何字元,包括空格和 tab 縮排。
  • 開始的 delimiter 前後的空格會被忽略掉。

也可將Here Document用在指令碼中:

#!/bin/bash
cat << EOF
This is a simple lookup program for good (and bad) restaurants
in Cape Town.
EOF

3 輸入輸出重定向

同時處理輸入和輸出的情況。

command < file1 >file2 # 把file1作为标准输入,file2作为标准输出

4 管道命令

4.1 |命令

管道命令(|)將一個命令的輸出,轉換為另外一個命令的輸入。

常見情形如篩選資料夾(如.)中包含特定名字(如y)的檔案:

ls . | grep y

這裡就使用了管道命令|,將ls .的輸出轉換為grep命令的輸入。管道命令可以連續使用,則是ls . | grep y | grep -v x:篩選出所有包含y但是不包含x的檔案。

管道命令會開啟新的執行緒來執行。比如說grep y就和ls .並不在同一個執行緒。

4.2 xargs對輸出進行操作

管道命令的輸出並不一定滿足下一個命令的輸入,有時候需要對管道命令進行一些操作再傳遞為輸入,此時就需要xargs命令。xargs(extended arguments),可以實現:

  1. 參數處理
  2. 從檔案中讀取資訊作為輸入

xargs後需要接後續處理的命令,如果沒有顯示指定,則預設為echo。雖然xargs的輸入可以包含空格和換行,但是經過echo的處理,都會變成空格。

ls . | ls -l

這裡報錯原因是ls -l的輸入不對,需要用xargs命令來轉換一下:

ls . | xargs ls -l

常見參數如下,為了說明問題,這裡構建了例子檔案。

 cat x.txt
shell_00.md
shell_01.md
shell_02.md
shell_03.md
shell_04.md
shell_05.md
  • -a xx 從檔案獲取輸入

     xargs -a x.txt file
    shell_00.md: Unicode text, UTF-8 text
    shell_01.md: Unicode text, UTF-8 text
    shell_02.md: Unicode text, UTF-8 text
    shell_03.md: Unicode text, UTF-8 text
    shell_04.md: Unicode text, UTF-8 text
    shell_05.md: Unicode text, UTF-8 text
  • -p 每執行一個參數時詢問一次使用者,需要輸入y+回車鍵 或者 yes+回車鍵表示確定,單獨輸入回車鍵表示不執行:

     xargs -a x.txt -p file
    file shell_00.md shell_01.md shell_02.md shell_03.md shell_04.md shell_05.md?...yes
    shell_00.md: Unicode text, UTF-8 text
    shell_01.md: Unicode text, UTF-8 text
    shell_02.md: Unicode text, UTF-8 text
    shell_03.md: Unicode text, UTF-8 text
    shell_04.md: Unicode text, UTF-8 text
    shell_05.md: Unicode text, UTF-8 text
  • -n num,命令執行時一次用的參數個數,預設用所有的,如果已經有的參數超過了這個數目,則會分行執行。

     xargs -a x.txt -p -n 2 file
    file shell_00.md shell_01.md?...yes
    shell_00.md: Unicode text, UTF-8 text
    shell_01.md: Unicode text, UTF-8 text
    file shell_02.md shell_03.md?...yes
    shell_02.md: Unicode text, UTF-8 text
    shell_03.md: Unicode text, UTF-8 text
    file shell_04.md shell_05.md?...yes
    shell_04.md: Unicode text, UTF-8 text
    shell_05.md: Unicode text, UTF-8 text
  • -t 先列印具體執行的命令,再執行

  • -i-I,將xargs的每項名稱,一般是一行一行賦值給{},可以用{}代替

  • -r no-run-if-empty 當 xargs 的輸入為空的時候則停止 xargs,不再去執行

  • -L-l num 從標準輸入一次讀取 num 行送給後面的命令

     xargs -a x.txt -t -L 2 file
    file shell_00.md shell_01.md
    shell_00.md: Unicode text, UTF-8 text
    shell_01.md: Unicode text, UTF-8 text
    file shell_02.md shell_03.md
    shell_02.md: Unicode text, UTF-8 text
    shell_03.md: Unicode text, UTF-8 text
    file shell_04.md shell_05.md
    shell_04.md: Unicode text, UTF-8 text
    shell_05.md: Unicode text, UTF-8 text

    需要和前面-n做一個區別。這裡指的是輸入的行數,而-n指的是輸出的參數的個數。

  • -d delimeter 分隔符,預設分隔符是空格,是 xargs 的輸入的分隔

     echo "ambmcmdm" | xargs -dm
    a b c d
  • -e-E flag, e 是 end 的意思,flag 必須是一個以空格分隔的標誌,當 xargs 分析到含有 flag 這個標誌的時候就停止

  • -s num 命令列的最大字元數,xargs 後面那個命令的最大命令列字元數

  • -x exit,配合-s使用

  • -P 修改最大的行程數,預設是 1,為 0 時候儘可能多。

4.3 tee命令

tee 讀取標準輸入的資料,並將其內容輸出成檔案。常見參數如下:

  • -a--append  附加到既有檔案的後面,而非覆蓋它。
  • -i--ignore-interrupts  忽略中斷訊號。

總結

本文介紹了 Shell 中輸入輸出重定向,以及通過管道命令來實現前一命令的輸出作為後一命令的輸入。以此介紹了xargstee命令。