Redirection in Linux 是一种在 Linux 中执行命令时,可以改变标准输入输出设备的功能。Linux 命令的基本流程是接收输入并产生输出,但是可以使用重定向技术来改变标准输入(stdin)或标准输出(stdout)的来源或目的地。例如,可以将命令的输出保存到文件中,而不是显示在屏幕上,或者可以将文件中的内容作为命令的输入,而不是从键盘输入。
Linux 中有三种数据流参与了命令的执行:
- 标准输入(stdin)是输入数据的来源。默认情况下,stdin 是从键盘输入的任何文本。它的流 ID 是 0。
- 标准输出(stdout)是命令的结果。默认情况下,它显示在屏幕上。它的流 ID 是 1。
- 标准错误(stderr)是命令产生的错误信息(如果有的话)。默认情况下,stderr 也显示在屏幕上。它的流 ID 是 2。
这些流包含了以纯文本形式存储在缓冲区内存中的数据。可以使用一些特殊的符号或命令来重定向这些流,例如:
- 输出重定向:使用 “>” 或 “>>” 符号来将 stdout 重定向到一个文件中。如果使用 “>” 符号,那么原有文件的内容会被覆盖;如果使用 “>>” 符号,那么新的输出会追加到原有文件的末尾。
- 输入重定向:使用 “<” 或 “<<” 符号来将 stdin 重定向到一个文件中。如果使用 “<” 符号,那么命令会从指定文件中读取输入;如果使用 “<<” 符号,那么命令会从终端中读取以指定分隔符结束的多行输入。
- 错误重定向:使用 “2>” 或 “2>>” 符号来将 stderr 重定向到一个文件中。如果使用 “2>” 符号,那么原有文件的内容会被覆盖;如果使用 “2>>” 符号,那么新的错误信息会追加到原有文件的末尾。
什么是文件描述符?
文件描述符是与系统上打开的文件关联的非负整数。需要注意的是,文件描述符绑定到一个进程,并且每个进程都是唯一的。打开新文件时,内核会返回与其关联的文件描述符。有三个与您的终端关联的标准文件描述符。
当bash启动时,默认情况下它会打开三个文件描述符(fd)
- stdin (fd 0)
- stdout (fd 1)
- stderr (fd 2)
所有这三个文件描述符都指向你的终端(例如 /dev/tty0),因此从你的终端读取输入,输出和错误被重定向到你的终端。
stdin (fd0) -----> /dev/tty0
stdout (fd1) -----> /dev/tty0
stderr (fd2) -----> /dev/tty0
这就是默认重定向的样子。但这些可以根据我们的需要进行更改。了解重定向如何工作的最佳方法是将它们可视化。
什么是重定向呢?
重定向是将默认位置操作到标准文件描述符(stdin、stdout、stderr)指向的位置的过程。
将命令的输出重定向到文件:
Syntax:
<command> n> file_name
Examples:
$ ls -la > list_file.txt
$ ls -la 1> list_file.txt
示例中的上述两个命令完全相同。如果未将文件描述符编号与重定向符号 (>) 一起指定,则默认为文件描述符 1(stdout 文件描述符)。请参阅下面的重定向可视化
fd0 -----> /dev/tty0
fd1 -----> list_file.txt
fd2 -----> /dev/tty0
将标准输出和标准输出重定向到文件:
这是常用的方案之一,其中命令的流、stdout 和 stderr 的输出都重定向到文件
$ command &> file
$ command >file 2&>1
以下是执行上述行后命令的文件描述符表的变化方式。
Original After the redirection
0 ------> /dev/tty0 0 ---------> /dev/tty
1 ------> /dev/tty0 1 ------|--> file
2 ------> /dev/tty0 2 ------|
重定向的顺序在这里很重要。如果重定向顺序被交换,则只有标准输出最终会重定向到文件。尝试按照上面的示例进行可视化
通过命令的 stdin 输入文件的内容:
将文件的内容重定向到命令的 stdin。此方案通常用于读取命令,其中文件可以作为读取的输入传递,而不是从终端读取
read -n 5 < input_file.txt
0 -----> input_file.txt
1 -----> /dev/tty0
2 -----> /dev/tty0
将执行的所有命令的 stderr 重定向到终端会话中的文件:
如果您想将 shell 会话中执行的所有命令的输出重定向到特定文件,下面的这个命令非常有用!
$ exec 2>file
$ test_command1
$ test_command2
如何打开新的文件描述符进行读写?
可以创建自定义文件描述符并将其指向文件,此文件描述符可用于读取和写入文件,具体取 决于您的数字。此用例介绍了内置 bash 命令 — exec 的用法。此内置命令 ,如果在重定向之前 指定,将使它们有效,直到您明确更改重定向或退出 shell 或脚本exec
使用自定义文件描述符打开文件进行读取:
# point a file descriptor to file
$ exec 7<file_name
# Reads a line from the file pointed by filedescriptor 7
$ read -u 7 line
# close fd after reading
$ exec 7>&-
使用自定义文件描述符写入文件:
这类似于将某些内容写入 stdout,只是您将有一个额外的步骤将文件描述符指向要写入的文件。
$ exec 3<file_write
$ echo "Test message" > &3
$ echo 3>&-
要打开文件以进行读取和写入,可以使用以下exec命令
#Use file descriptor for both reading and writing - Filename:
$ exec 3 <>
更多 bash 单行代码的示例:
丢弃命令输出:
重定向到特殊文件 /dev/null 将避免将命令的输出打印到 stdout。/dev/null 是 Linux 中用于写入输出的众多虚拟文件之一。写入 /dev/null 的任何内容都会被遗忘,并且永远不会打印出来
$ test_command < /dev/null
从终端输入命令:
可以通过从终端获取输入来创建文件并在单个命令中添加内容。下面是一个示例。以下<<EOF的语法称为heredoc。
$ cat > '' <<EOF
Always in love with bash and
all the things we could do with it.
EOF
将标准输出打印到终端和文件:
从技术上讲,Tee 不是 bash 的一部分,但经常使用。它将输入流复制到标准输出以及零个或多个文件。相信我,这非常方便,尤其是在调试时。
command -----> tee -----> stdout
|--------> file
Pipe在哪里使用?
Pipe 是 Linux 中的一种重定向功能,可以将一个命令/程序/进程的输出发送到另一个命令/程序/进程作为输入,从而实现命令之间的协作。Pipe 的符号是 “|”,可以用来连接多个命令,形成一个命令管道。例如:
ls | grep "txt" | wc -l
这个命令管道的作用是先列出当前目录下的所有文件,然后筛选出包含 “txt” 的文件,最后统计这些文件的数量。每个命令的输出都成为下一个命令的输入,直到最后一个命令的输出显示在终端上。
pipe最常见的用例是将一个命令的输出作为另一个命令的输入发送。
Syntax:
command1 | command2
Examples:
$ ls . >
$ wc -l
The above two commands are equivalent to this one-liner
$ ls . | wc -l
此单行可用于将命令的 stdout 和 stderr 发送到另一个命令的 stdin。
command1 2>&1 | command2
重定向单行文本,作为另一个命令的输入
echo “Test text” | test_command
“Test text”现在输入test_command.
本文介绍了 Linux 中的重定向和管道功能,以及如何使用它们来实现命令之间的协作和数据流的控制。通过一些简单的例子,我们展示了如何使用 test 命令来测试命令或表达式的有效性,以及如何检查文件的类型和权限。我还介绍了一些常用的重定向和管道操作符,以及它们的含义和用法。希望本文能够帮助你更好地理解和使用 Linux 中的重定向和管道功能,提高你的命令行技能和效率。
感谢你阅读本文,如果你觉得本文对你有帮助,请给我一个赞或者留下你的评论。如果你有任何问题或建议,也欢迎你与我联系。我会尽力回复你的问题,并不断改进我的博客内容。再次感谢你的支持和关注,祝你学习愉快!