在解釋什麼是重定向之前,先來說說什麼是文件描述符
文件描述符可以理解為 Linux 系統為文件分配的一個數字,范圍是 0-3 ,用戶也可以自定義文件描述符,但是自定文件描述符不在這裡的討論范圍
文件描述符(file descriptor)
文件描述符的存儲位置位於 /proc/self/fd
,文件描述符是通過一系列軟鏈接指向的默認輸出設備,這裡我們的默認設備就是模擬終端
模擬終端的文件可以使用命令 tty 來查看
[divent@bash]$ ls -al /proc/self/fd
total 0
lrwx------. 1 divent divent 64 Aug 15 14:09 0 -> /dev/pts/0
lrwx------. 1 divent divent 64 Aug 15 14:09 1 -> /dev/pts/0
lrwx------. 1 divent divent 64 Aug 15 14:09 2 -> /dev/pts/0
對於一條 Linux 的命令執行的過程如下
一個命令執行以前,會准備好所有的輸入輸出,默認分別綁定 stdin
(0),stdout
(1),stderr
(2)。如果在准備命令的時候出現錯誤,那麼這個命令將不會執行
command [OPTION]{>,>>} [File]
option:
1 standard output(default)
2 standard error output
& all output
>
為覆蓋輸出,>>
為追加輸出
#假設當前文件夾有文件 test2
[divent@bash]$ ls test test2
ls: cannot access test: No such file or directory
test2
這裡可以看到同時擁有的標准輸出與標准錯誤輸出都顯示在了屏幕上
現在我們要將輸出寫入到文件中
#假設已經有文件 test2 , test3
[divent@bash]$ ls test test2 > test3
ls: cannot access test: No such file or directory
[divent@bash]$ cat test3
test2
因為這裡的文件只默認接受了標准輸出,所以標准錯誤輸出就輸出到了終端上
我們也可以將標准錯誤輸出寫入到文件
#假設已經有文件 test2 , stderr
[divent@bash]$ ls test test2 2> stderr
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory
這裡獲得的結果就和剛剛的結果正好相反
我們也可以將標准輸出與標准錯誤輸出都重定向到不同的文件
#假設已經有文件 test2 , stdout , stderr
[divent@bash]$ ls test test2 1> stdout 2>stderr
[divent@bash]$ cat stdout
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory
這裡我們就將兩個不同的輸出輸出到了指定的文件中
我們也可以將兩個輸出同時輸出到同一個文件中
#假設已經有文件 test2 , test3
[divent@bash]$ ls test test2 &> test3
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2
這裡就使用 \& 將兩種輸出同時輸出到了同一個文件
我們也可以只接受某一種輸出,而將其他的輸出導向到其他地方
#假設已經有文件 test2
[divent@bash]$ ls test test2 2>&-
test2
[divent@bash]$ ls test test2 2>/dev/null
test2
# &- 意義為關閉這個輸出,/dev/null 是 linux 的黑洞設備
>
操作符,會判斷右邊文件是否存在,如果存在就先刪除,並且創建新文件。不存在直接創建。 無論左邊命令執行是否成功。右邊文件都會變為空。>>
操作符,判斷右邊文件是否存在,如果不存在,先創建。以添加方式打開文件,會分配一個文件描述符[不特別指定,默認為1]然後,與左邊對應的輸出綁定。command {<} [File] {<<} [Word]
這裡的
<
與<<
意義不是類似於輸出重定向的操作符,<
是從文件中取出數據到指定的文件中
[divent@bash]$ cat > newfile
123
abc
456
[divent@bash]$cat newfile
123
abc
456
#這裡使用 Ctrl + D 可以結束輸入,從鍵盤輸入的數據會保存存到 newfile 文件中
cat 命令直接使用的話可以直接接收鍵盤的輸入
現在來嘗試從文件中輸入
#這裡的示例我們使用剛才創建的 test3 文件
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2
[divent@bash]$ cat > newfile < test3
[divent@bash]$ cat newfile
ls: cannot access test: No such file or directory
test2
這裡的先將文件中的數據提取到了命令 cat
中 ,然後由 cat
寫入到 newfile
中
除了使用系統給你定義的文件描述符以外,用戶還可以自己自定義文件描述符,首先使用 ulimit -n
來查看文件描述符的上限,然後使用命令 exec
來為一個文件添加文件描述符
#首先查看一下現在已經被占用的文件描述符
[divent@bash]$ ls /proc/self/fd
0 1 2 3
#這個時候我們可以使用 exec 命令來為一個文件賦予一個文件描述符
[divent@bash]$ touch /tmp/test && exec 5>/tmp/test
#然後我們再查看文件描述符 5
[divent@bash]$ ls -al /proc/self/fd/5
l-wx------. 1 divent divent 64 Aug 15 14:54 /proc/self/fd/5 -> /tmp/test
#現在我們使用自己自定義的文件描述符來重定向輸出
[divent@bash]$ ls -l /etc >&5
#然後我們再來查看文件中的數據, 因為文件中有數據,這裡就只取出前 5 行作為示例
[divent@bash]$ head -n 5 /tmp/test
total 1936
drwxr-xr-x. 3 root root 4096 Jun 10 22:12 abrt
-rw-r--r--. 1 root root 16 Jun 9 16:56 adjtime
-rw-r--r--. 1 root root 1518 Feb 22 22:11 aliases
drwxr-xr-x. 2 root root 4096 Jun 10 22:11 alsa
#我們也可以使用 exec 來將文件的默認輸出指向文件
[divent@bash]$ exec 1>&5
[divent@bash]$ ls -l /etc
#這個時候就會發現沒有輸出了,已經輸出內容已經到了 /tmp/test 中了
#如果想要恢復輸出,將默認輸出重新指向當前 /dev/pts/0 即可
[divent@bash]$ exec 1>/dev/pts/0
#關閉文件描述符
[divent@bash]$ exec 5>&-
#最後我們查看一下
[divent@bash]$ ls /proc/self/fd
0 1 2 3