解释:Linux中的输入、输出和错误重定向

如果您熟悉基本的 Linux 命令,您还应该学习输入输出重定向的概念。

您已经知道 Linux 命令的功能。 它接受输入并为您提供输出。 这里有几个玩家在现场。 让我告诉你他们。

标准输入、标准输出和标准错误

当您运行 Linux 命令时,有三个数据流在其中发挥作用:

  • 标准输入(标准输入) 是输入数据的来源。 默认情况下,stdin 是从键盘输入的任何文本。 它的流 ID 为 0。
  • 标准输出(标准输出) 是命令的结果。 默认情况下,它显示在屏幕上。 它的流 ID 为 1。
  • 标准误差 (标准错误) 是命令产生的错误消息(如果有的话)。 默认情况下,stderr 也会显示在屏幕上。 它的流 ID 为 2。

这些流包含所谓的纯文本数据 缓冲存储器.

把它想象成水流。 你需要一个水源,一个水龙头 example. 您将管道连接到它,您可以将其存储在桶中(文件)或给植物浇水(打印)。 如果需要,您还可以将其连接到另一个水龙头。 基本上,您正在重定向水。

Linux 也有这种重定向的概念,您可以将标准输入、标准输出和标准错误从其通常的目的地重定向到另一个文件或命令(甚至是打印机等外围设备)。

让我展示重定向的工作原理以及如何使用它。

输出重定向

第一种也是最简单的重定向形式是输出重定向,也称为标准输出重定向。

您已经知道,默认情况下,命令的输出会显示在屏幕上。 为了 example,我使用 ls 命令列出所有文件,这是我得到的输出:

[email protected]:~$ ls
appstxt  new.txt  static-ip.txt

使用输出重定向,您可以将输出重定向到文件。 如果此输出文件不存在,shell 将创建它。

command > file

为了 example,让我将 ls 命令的输出保存到一个名为 output.txt 的文件中:

[email protected]:~$ ls > output.txt

输出文件是预先创建的

你认为这个输出文件的内容应该是什么? 让我用 cat 命令给你一个惊喜:

[email protected]:~$ cat output.txt 
appstxt
new.txt
output.txt
static-ip.txt

你是否 请注意,其中包含 output.txt? 我特意选了这个 example 给你看这个。

将 stdout 重定向到的输出文件是在运行预期命令之前创建的。 为什么? 因为它需要准备好将输出发送到的输出目的地。

追加而不是破坏

一个经常被忽略的问题是,如果你重定向到一个已经存在的文件,shell 将删除 (破坏者) 首先是文件。 这意味着输出文件的现有内容将被删除并替换为命令的输出。

您可以使用 >> 重定向语法追加而不是覆盖它。

command >> file

提示:您可以使用以下命令在当前 shell 会话中禁止破坏:set -C

为什么要重定向标准输出? 您可以存储输出以供将来参考并在以后进行分析。 当命令输出太大并且占据整个屏幕时,它特别有用。 这就像收集日志。

管道重定向

管道重定向

在看到标准输入重定向之前,您应该了解管道重定向。 这更常见,可能您会经常使用它。

使用管道重定向,您可以将命令的标准输出发送到另一个命令的标准输入。

command 1 | command 2

给你看一个实用的 example. 比如说,你想计算当前目录中可见文件的数量。 您可以使用 ls -1(它是数字一,而不是字母 L)来显示当前目录中的文件:

[email protected]:~$ ls -1
appstxt
new.txt
output.txt
static-ip.txt

您可能已经知道 wc 命令用于计算文件中的行数。 如果将这两个命令与管道结合使用,您将得到以下结果:

[email protected]:~$ ls -1 | wc -l
4

使用管道,两个命令共享相同的内存缓冲区。 第一个命令的输出存储在缓冲区中,然后将同一缓冲区用作下一个命令的输入。

您将看到管道中最后一个命令的结果。 这很明显,因为早期命令的标准输出被馈送到下一个命令而不是进入屏幕。

管道重定向或管道不限于仅连接两个命令。 只要一个命令的输出可以作为下一个命令的输入,就可以连接更多的命令。

command_1 | command_2 | command_3 | command_4

记住标准输出/标准输入是一大块数据,而不是文件名

一些新的 Linux 用户在使用重定向时会感到困惑。 如果命令返回一堆文件名作为输出,则不能使用这些文件名作为参数。

为了 example,如果使用 find 命令查找所有以 .txt 结尾的文件,则无法通过管道将找到的文件移动到新目录,而不是直接这样:

find . -type f -name "*.txt" | mv destination_directory

这就是为什么你会经常看到 find 命令与 exec 或 xargs 命令结合使用的原因。 这些特殊命令“将带有一堆文件名的文本转换为文件名”,可以作为参数传递。

find . -type f -name "*.txt" | xargs -t -I{} mv {} ../new_dir

输入重定向

标准输入重定向

您可以使用标准输入重定向将文本文件的内容传递给如下命令:

command < file

你不会看到标准输入被大量使用。 这是因为大多数 Linux 命令接受文件名作为参数,因此通常不需要标准输入重定向。

拿这个 example:

head < filename.txt

上面的命令可能只是 头文件名.txt (没有 <)。

并不是说标准输入重定向完全没用。 一些命令依赖它。 以 tr 命令为 example. 这个命令可以做很多事情,但是在 example 下面,它将输入文本从小写转换为大写:

tr a-z A-Z < filename.txt

实际上,建议在管道上使用标准输入,以避免不必要地使用 cat 命令。

为了 example,很多人会用上面的 example 与 cat 然后使用 tr 就可以了。 坦率地说,这里没有必要使用 cat 。

cat filename.txt | tr a-z A-Z

合并重定向

您可以根据需要组合标准输入、标准输出和管道重定向。

为了 example,下面的命令列出当前目录中的所有 .txt 文件,然后对这些 .txt 文件进行计数并将输出保存到新文件中。

ls *.txt | wc -l > count.txt

错误重定向

有时当您运行某些命令或脚本时,您会看到它在屏幕上显示一条错误消息。

[email protected]:~$ ls -l ffffff > output.txt
ls: cannot access 'ffffff': No such file or directory

在本文开头,我提到有三个数据流,stderr 是默认显示在屏幕上的输出数据流之一。

您也可以重定向标准错误。 由于它是一个输出数据流,因此您可以使用与 stdout 重定向相同的 > 或 >> 重定向符号。

但是当它们都是输出数据流时,你如何区分 stdout 和 stderr 呢? 通过它们的流 ID(也称为文件描述符)。

数据流流 ID
标准输入0
标准输出1
标准错误2
-t,-列表
-u,-更新
-X,–提取,–获取
-j,–bzip2
-z,–gzip、–gunzip、–ungzip

默认情况下,当您使用输出重定向符号 > 时,它实际上表示 1>。 换句话说,您是说这里正在输出 ID 为 1 的数据流。

当您必须重定向标准错误时,您可以使用它的 ID,如 2> 或 2>>。 这表示输出重定向是针对数据流 stderr (ID 2)。

Stderr 重定向示例

让我用一些例子向你展示。 假设你只是想保存错误,你可以使用这样的东西:

[email protected]:~$ ls fffff 2> error.txt
[email protected]:~$ cat error.txt 
ls: cannot access 'fffff': No such file or directory

那很简单。 让我们让它稍微复杂一些(并且有用):

[email protected]:~$ ls -l new.txt ffff > output.txt 2> error.txt 
[email protected]:~$ cat output.txt 
-rw-rw-r-- 1 abhishek abhishek 0 May  5 10:25 new.txt
[email protected]:~$ cat error.txt 
ls: cannot access 'ffff': No such file or directory

在上述 example, ls 命令尝试显示两个文件。 对于一个文件,它会成功,而对于另一个文件,它会出错。 所以我在这里所做的是将标准输出重定向到 ouput.txt(带 >),将标准错误重定向到 error.txt(带 2>)。

您还可以将 stdout 和 stderr 重定向到同一个文件。 有办法做到这一点。

在下面 example,我首先将stderr(带2>>)以附加模式发送到combined.txt文件。 然后,标准输出(带 >>)以附加模式发送到同一个文件。

[email protected]:~$ ls -l new.txt fff 2>> combined.txt >> combined.txt 
[email protected]:~$ cat combined.txt 
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 abhishek abhishek 0 May  5 10:25 new.txt

另一种方法,这是首选方法,是使用类似 2>&1 的方法。 大致可以翻译为“将stderr重定向到与stdout相同的地址”。

让我们拿上一个 example 这次使用 2>&1 将 stdout 和 stderr 都重定向到同一个文件。

[email protected]:~$ ls -l new.txt fff > output.txt 2>&1
[email protected]:~$ cat output.txt 
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 abhishek abhishek 0 May  5 10:25 new.txt

请记住,您不能使用 2>>&1 考虑在附加模式下使用它。 2>&1 已经进入附加模式。

您也可以先使用 2>,然后使用 1>&2 将 stdout 重定向到与 stderr 相同的文件。 基本上,它是“>&”将一个输出数据流重定向到另一个。

概括

  • 共有三个数据流。 一个输入,stdin (0) 和两个输出数据流 stdout (1) 和 stderr (2)。
  • 键盘是默认的标准输入设备,屏幕是默认的输出设备。
  • 输出重定向与 > 或 >> 一起使用(用于追加模式)。
  • 输入重定向与 < 一起使用。
  • 可以使用 2> 或 2>> 重定向 stderr。
  • 可以使用 2>&1 组合标准错误和标准输出。

由于您正在学习重定向,因此您还应该了解 tee 命令。 此命令使您能够同时显示到标准输出并保存到文件。

我希望你喜欢这个关于 Linux 重定向的详细指南。 如果您仍有疑问或有改进本文的建议,请在评论部分告诉我。