数字化开发者大会:混合云 (亚太地区专场:9 月 24 日 上午 11:00) 即刻报名

流、管道和重定向

概述

本教程将介绍 Linux 中重定向标准 IO 流的基本技术。学习:

  • 重定向标准 IO 流:标准输入、标准输出和标准错误
  • 传输一个命令的输出作为另一个命令的输入
  • 将输出发送到 stdout 和文件
  • 使用命令输出作为另一个命令的参数

本教程可以帮助您针对 Linux Server Professional (LPIC-1) 考试 101 的主题 103 中的目标 103.4 进行应考准备。该目标的权重为 4。

输入、输出和流

Linux shell(比如 Bash)以字符序列或 的形式接收输入和发送输出。每个字符与它之前和之后的字符独立。字符未组织为结构化记录或固定大小的字符块。流使用了文件 IO 技术访问,无论是否是来自或传到文件、键盘、显式窗口或某种其他 IO 设备的实际字符流。Linux shell 使用 3 种标准 I/O 流,每种流与一种著名的文件描述符相关联:

  1. stdout标准输出流 ,它显示来自命令的输出。它拥有文件描述符 1。
  2. stderr标准错误流 ,它显示来自命令的错误输出。它拥有文件描述符 2。
  3. stdin标准输入流 ,它向命令提供输入。它拥有文件描述符 0。

输入流向程序提供输入,这些输入通常来自终端击键。输出流打印文本字符,通常打印到终端。终端最初为 ASCII 打字机或显示终端,但现在通常是图形桌面上的文本窗口。

如果您已学习了教程 “学习 Linux 101 :文本流和过滤器 ”,那么您应该熟悉本教程中的一些内容。

前提条件

要从本系列教程中获得最大收获,您应该拥有 Linux 的基本知识和一个正常工作的 Linux 系统,您可以在这个系统上实践本教程中涵盖的命令。有时,程序的不同版本会得到不同的输出格式,所以您的结果可能并不总是与这里给出的清单和图完全相同。本教程中的示例使用了 Fedora 22,它们应适用于任何 Linux 系统。

设置示例

在本教程中,将使用教程 “学习 Linux 101: 文本流和过滤器 ” 中创建的一些文件来练习这些命令。但是,如果您尚未阅读该教程,或者未保存所使用的文件,不必担心!首先在您的主目录中创建一个名为 lpi103-4 的新子目录,并在其中创建必要的文件。为此,可打开一个文本窗口,采用您的主目录作为当前目录。然后将 创建示例文件 的内容复制并粘贴到该窗口中来运行相关命令,这些命令将会创建 lpi103-4 子目录和您将使用的文件。 提示: 在大多数 X 视窗® 系统中,按住鼠标中键会将选定的文本粘贴在光标位置。选定的文本可位于同一个或另一个窗口中。

创建示例文件
mkdir -p lpi103-4 && cd lpi103-4 && {
 echo -e "1 apple\n2 pear\n3 banana" > text1
 echo -e "9\tplum\n3\tbanana\n10\tapple" > text2
 echo "This is a sentence. " !#:* !#:1->text3
 split -l 2 text1
 split -b 17 text2 y
 ls; }

您的窗口应类似于 创建示例文件 – 输出 ,您的当前目录现在应该是新建的 lpi103-4 目录。

创建示例文件 – 输出
[ian@atticf22 ~]$ mkdir -p lpi103-4 && cd lpi103-4 && {
> echo -e "1 apple\n2 pear\n3 banana" > text1
> echo -e "9\tplum\n3\tbanana\n10\tapple" > text2
> echo "This is a sentence. " !#:* !#:1->text3
echo "This is a sentence. " "This is a sentence. " "This is a sentence. ">text3
> split -l 2 text1
> split -b 17 text2 y
> ls; }
text1  text2  text3  xaa  xab  yaa  yab

重定向标准 IO

尽管标准输入和输出模型是发往和来自 ASCII 终端的顺序字符流,但您可能希望在文件中准备好输入数据,或者将输出或错误信息保存在文件中。这时就需要使用 重定向

重定向输出

可通过两种方式将输出重定向到文件:

  • n >: 将来自文件描述符 n 的输出重定向到某个文件。您必须拥有该文件的写权限。如果该文件不存在,则需要创建它。如果它已经存在,通常会毫无预兆地丢失现有内容。
  • n >>: 也将来自文件描述符 n 的输出重定向到某个文件。同样地,您必须拥有该文件的写权限。如果该文件不存在,则需要创建它。如果它已经存在,输出会被附加到现有文件。

n> 或 n>> 中的 n 指的是 文件描述符 。如果省略它,则会假设使用的是标准输出(文件描述符 1)。 输出重定向 演示了如何使用重定向和您之前在 lpi103-4 目录中创建文件将 ls 命令的标准输出和标准错误分开。其中还演示了如何将输出附加到现有文件。

输出重定向
[ian@atticf22 lpi103-4]$ ls x* z*
ls: cannot access z*: No such file or directory
xaa  xab
[ian@atticf22 lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
[ian@atticf22 lpi103-4]$ ls w* y*
ls: cannot access w*: No such file or directory
yaa  yab
[ian@atticf22 lpi103-4]$ ls w* y* >>stdout.txt 2>>stderr.txt
[ian@atticf22 lpi103-4]$ cat stdout.txt
xaa
xab
yaa
yab
[ian@atticf22 lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
ls: cannot access w*: No such file or directory

我说过使用 n> 的输出重定向通常会覆盖现有文件。您可以使用内建命令 setnoclobber 选项来控制此行为。如果已设置它,可以使用 n>| 覆盖它,如 使用 noclobber 的输出重定向 所示。

使用 noclobber 的输出重定向
[ian@atticf22 lpi103-4]$ set -o noclobber
[ian@atticf22 lpi103-4]$ ls x* z* >stdout.txt 2>stderr.txt
bash: stdout.txt: cannot overwrite existing file
[ian@atticf22 lpi103-4]$ ls x* z* >|stdout.txt 2>|stderr.txt
[ian@atticf22 lpi103-4]$ cat stdout.txt
xaa
xab
[ian@atticf22 lpi103-4]$ cat stderr.txt
ls: cannot access z*: No such file or directory
[ian@atticf22 lpi103-4]$ set +o noclobber #restore original noclobber setting

有时,您可能希望将标准输出和标准错误都重定向到一个文件中。通常,会对自动化流程或后台作业这么做,以便可以在以后检查输出。使用 &> 或 &>> 将标准输出和标准错误都重定向到同一个位置。另一种方法是重定向文件描述符 n ,然后使用结构 m>&n 或 m>>&n 将文件描述符 m 重定向到相同位置。重定向输出的顺序很重要。例如,

command 2>&1 >output.txt

不同于

command >output.txt 2>&1

在第一种情况下,stderr 被重定向到当前的 stdout 位置,然后将 stdout 重定向到 output.txt,但第二次重定向仅会影响 stdout,而不会影响 stderr。在第二种情况下,stderr 被重定向到当前的 stdout 位置,也就是 output.txt。我们在 将两个流重定向到一个文件 中演示了这些重定向。请注意,在最后一个命令中,标准输出在标准错误之后重定向,所以标准错误仍输出到终端窗口。

将两个流重定向到一个文件
[ian@atticf22 lpi103-4]$ ls x* z* &>output.txt
[ian@atticf22 lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@atticf22 lpi103-4]$ ls x* z* >output.txt 2>&1
[ian@atticf22 lpi103-4]$ cat output.txt
ls: cannot access z*: No such file or directory
xaa
xab
[ian@atticf22 lpi103-4]$ ls x* z* 2>&1 >output.txt # stderr does not go to output.txt
ls: cannot access z*: No such file or directory
[ian@atticf22 lpi103-4]$ cat output.txt
xaa
xab

在其他时候,您可能希望完全忽略标准输出或标准错误。为此,可将合适的流重定向到空文件 /dev/null。 使用 /dev/null 忽略输出 展示了如何重定向来自 ls 命令的错误输出,还使用 cat 命令展示了 /dev/null 的确是空的。

使用 /dev/null 忽略输出
[ian@atticf22 lpi103-4]$ ls x* z* 2>/dev/null
xaa  xab
[ian@atticf22 lpi103-4]$ cat /dev/null

重定向输入

就像重定向 stdout 和 stderr 流一样,您还可以使用 < 运算符重定向来自文件的 stdin。如果已经学习了教程 “学习 Linux 101 :文本流和过滤器 ”,您可能会想起,在对 sort 和 uniq 的讨论中,使用了 tr 命令将 text1 文件中的空格替换为制表符。在该示例中,使用了 cat 命令的输出来创建 tr 命令的标准输入。无需多余地调用 cat ,您现在可以使用输入重定向将空格转换为制表符,如 输入重定向 所示。

输入重定向
[ian@atticf22 lpi103-4]$ cat text1
1 apple
2 pear
3 banana
[ian@atticf22 lpi103-4]$ tr ' ' '\t'<text1
1      apple
2      pear
3      banana

Shell(包括 bash)也拥有 here-document 概念,这是输入重定向的另一种形式。它将 << 和一个单词结合构成一个标记,比如与 END 结合来表示输入结束。 使用 here-document 的输入重定向 演示了此概念,其中按第二个字段 (fruit name) 对输入进行了排序。

使用 here-document 的输入重定向
[ian@atticf22 lpi103-4]$ sort -k2 <<END
> 1 apple
> 2 pear
> 3 banana
> END
1 apple
3 banana
2 pear

您可能想知道能否仅输入 sort -k2 ,输入您的数据,然后按下 Ctrl-d 来表示输入结束。简单答案是可以,您一定不熟悉 here-document。实际答案是 shell 脚本中通常使用 here-document。(脚本没有其他方式来表明应将那几行脚本视为输入。)因为 shell 脚本广泛使用制表符进行缩进来确保可读性,所以 here-document 还有另一个特征。如果使用 <<- 而不是 <<,则会删除前导制表符。

使用 here-document 的输入重定向 中,使用命令替换创建了一个强制制表符,然后创建了一段仅包含两个 cat 命令的很短的 shell 脚本,每个命令从一个 here-document 读取信息。请注意,您使用 END 作为您从终端读取的 here-document 的标记。如果在脚本中使用同一个单词作为标记,则会导致过早结束输入。所以,可使用 EOF 代替。创建脚本后,使用 . (点号)命令 导入 它,这意味着在当前 shell 上下文中运行它。

使用 here-document 的输入重定向
 [ian@atticf22 lpi103-4]$ ht=$(echo -en "\t")
 [ian@atticf22 lpi103-4]$ cat<<END>ex-here.sh
 > cat <<-EOF
 > apple
 > EOF
 > ${ht}cat <<-EOF
 > ${ht}pear
 > ${ht}EOF
 > END
 [ian@atticf22 lpi103-4]$ cat ex-here.sh
 cat <<-EOF
 apple
 EOF
     cat <<-EOF
     pear
     EOF
 [ian@atticf22 lpi103-4]$ . ex-here.sh
 apple
 pear

您将在本系列的后续教程中进一步学习命令替换和脚本编写。请参阅我们的 系列路线图 ,获得本系列中每篇教程的说明和链接。

创建管道

在教程 “学习 Linux 101 :文本流和过滤器 ” 中,我介绍过 过滤 是获取输入文本流并在文本上执行某种转换,然后将它发送到输出流的过程。通常,这种过滤通过构造命令 管道 来完成,其中来自一个命令的输出 通过管道传输重定向 而被用作下一个命令的输入。管道的这种使用方式并不仅限于文本流,但这是它们的常见用途。

通过管道将 stdout 传输到 stdin

您在两个命令之间使用 |(竖线)运算符,将第一个命令的 stdout 定向到第二个命令的 stdin。可通过添加更多命令和更多竖线运算符来构造更长的管道。任何命令都可以有选项或参数。许多命令使用连字符 (-) 代替文件名作为参数,以表明输入应来自 stdin 而不是文件。请检查命令的手册页进行确认。构造分别拥有有限功能的命令的长管道,是 Linux 和 UNIX® 完成任务的一种常见方式。在 通过管道将输出传经多个命令 中的虚构管道中, command2command3 都有一些参数,而 command3 使用 - 参数表明输入来自 stdin,还使用了其他一些虚构的参数。

通过管道将输出传经多个命令
command1 | command2 paramater1 | command3 parameter1 - parameter2 | command4

要注意的一点是,管道 将 stdout 传输到 stdin。您不能使用 2| 来单独传输 stderr,至少使用您目前了解的工具不能这么做。如果 stderr 已重定向到 stdout,两个流都将通过管道传输。 通过管道传输两个输出流 演示了一个不太可能出现的 ls 命令,它拥有 4 个未按字母顺序排列的通配符参数,然后使用一个管道对正常和错误输出组合进行排序。

通过管道传输两个输出流
[ian@atticf22 lpi103-4]$ ls y* x* z* u* q*
ls: cannot access z*: No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access q*: No such file or directory
xaa  xab  yaa  yab
[ian@atticf22 lpi103-4]$  ls y* x* z* u* q*  2>&1 |sort
ls: cannot access q*: No such file or directory
ls: cannot access u*: No such file or directory
ls: cannot access z*: No such file or directory
xaa
xab
yaa
yab

这里有一点很有趣。如果将 ls 输出到终端,输出将格式化为填满终端窗口的列数。如果它被重定向,则每行一个输出条目。这样就更容易对一组文件中的每一个执行进一步操作。

Linux 和 UNIX 系统中的管道的一个优点是,不同于其他一些流行的操作系统,管道不会涉及到中间文件。第一个命令的 stdout 不会 写入到一个文件,然后由第二个命令读取。在教程 “学习 Linux,101 :文件和目录管理 ” 中,我们学习了如何使用 tar 命令在一步中存档和压缩文件。如果在您使用的 UNIX 系统上, tar 命令不支持使用 -z (表示 gzip)或 -j (表示 bzip2)执行压缩,不用担心。您可以使用一个类似

bunzip2 -c somefile.tar.bz2 | tar -xvf -

的管道来执行该任务。

以一个文件而不是 stdout 作为管道开头

在以前的管道中,首先使用一个命令生成输出,然后将该输出传输到管道的每个阶段。如果您想以一个已存在的数据文件作为开头,该怎么办?许多命令接受 stdin 或一个文件作为输入,所以不用担心这些命令。接受来自 stdin 的输入并将输出发送到 stdout 的程序通常被称为 过滤器 。如果您有一个需要使用来自 stdin 的输入的过滤器,您可能会考虑使用 cat 命令将文件复制到 stdout,然后将它传输到命令,这种方法将会起效。但是,您可以对第一个命令使用输入重定向,然后将该命令的输出传输到管道的剩余部分,这是更常见的解决方案。只需使用 < 运算符将第一个命令的 stdin 重定向到您想要处理的文件。您会在下一节看到一个例子。

使用输出作为参数

在前面对管道的讨论中,您学习了如何获取一个命令的输出并用作另一个命令的输入。但是,假设您想使用一个命令的输出或一个文件的内容作为另一个命令的参数,而不是作为输入。管道无法完成此任务。三种常见的方法是:

  1. xargs 命令
  2. -exec 选项的 find 命令
  3. 命令替换

现在来看看前两种方法。在 使用 here-document 的输入重定向 中创建强制制表符时,您已经看到了命令替换的例子。命令替换可用在命令行上,但更常用在脚本中;您将在本系列的后续教程中进一步了解它和脚本编写。请参阅我们的 系列路线图 ,获得本系列中每篇教程的说明和链接。

使用 xargs 命令

xargs 命令读取标准输入,然后使用该输入作为餐胡来构建和执行命令。如果未提供命令,则使用 echo 命令。 使用 xargs 是一个使用您的 text1 文件的基本示例,该文件包含 3 行,每行两个单词。

使用 xargs
[ian@atticf22 lpi103-4]$ cat text1
1 apple
2 pear
3 banana
[ian@atticf22 lpi103-4]$ xargs < text1
1 apple 2 pear 3 banana

那么为什么 xargs 只有一行输出?默认情况下, xargs 会在空格处中断输入,而且得到的每个标记变成一个参数。但是,在 xargs 构建命令时,它会一次传递尽可能多的参数。您可以使用 -n--max-args 参数覆盖此行为。 使用 xargsecho 演示了两种形式的用法,并向 xargs 中添加了对 echo 的显式调用。

使用 xargsecho
[ian@atticf22 lpi103-4]$ xargs<text1 echo "arg list:"
arg list: 1 apple 2 pear 3 banana
[ian@atticf22 lpi103-4]$ xargs --max-args 3 <text1 echo "arg list:"
arg list: 1 apple 2
arg list: pear 3 banana
[ian@atticf22 lpi103-4]$ xargs -n 1 <text1 echo "arg list:"
arg list: 1
arg list: apple
arg list: 2
arg list: pear
arg list: 3
arg list: banana

如果输入包含放在单或双引号中的空格,或者通过反斜杠转义的空格,那么 xargs 不会在这些位置中断输入。 结合使用 xargs 和引号 演示了此用法。

结合使用 xargs 和引号
 [ian@atticf22 lpi103-4]$ echo '"4 plum"' | cat text1 -
 1 apple
 2 pear
 3 banana
"4 plum"
 [ian@atticf22 lpi103-4]$ echo '"4 plum"' | cat text1 - | xargs -n 1
 1
 apple
 2
 pear
 3
 banana
 4 plum

目前为止,所有参数都被添加到命令的末尾。如果您需要将它们用作参数且后跟其他参数,可以使用 -I 选项指定一个替换字符串。只要您要求 xargs 执行的命令中出现替换字符串,它就会被替换为一个参数。这么做时,仅会将一个参数传递给每个命令。但是,该参数是使用整行输入创建的,而不是单个标记。也可以使用 xargs-L 选项,让它将各行视为参数,而不是视为空格分隔的单独标记(默认情况)。使用 -I 选项表示 -L 1使用 xargs 和多行输入 给出了使用 -I-L 的例子。

使用 xargs 和多行输入
[ian@atticf22 lpi103-4]$ xargs -I XYZ echo "START XYZ REPEAT XYZ END" <text1
START 1 apple REPEAT 1 apple END
START 2 pear REPEAT 2 pear END
START 3 banana REPEAT 3 banana END
[ian@atticf22 lpi103-4]$ xargs -IX echo "<X><X>" <text2
<9      plum><9      plum>
<3      banana><3      banana>
<10      apple><10      apple>
[ian@atticf22 lpi103-4]$ cat text1 text2 | xargs -L2
1 apple 2 pear
3 banana 9 plum
3 banana 10 apple

我们的例子使用了简单的文本文件来演示我们介绍的内容,但您可能很少希望对 xargs 使用这样的输入。通常,您会处理一个命令(比如 lsfindgrep )生成的庞大的文件列表。 使用 xargs 和文件列表 展示了一种通过 xargs 将目录清单传递给命令(比如 grep )的方式。

使用 xargs 和文件列表
[ian@atticf22 lpi103-4]$ ls |xargs grep "1"
text1:1 apple
text2:10      apple
xaa:1 apple
yaa:1

在上一个例子中,如果一个或多个文件名包含空格,会发生什么?如果像在 使用 xargs 和文件列表 中一样使用该命令,则会获得一个错误。实际上,您的文件列表可能来自自定义脚本或命令等来源,而不是 ls ,或者您可能希望将它传递给其他一些管道阶段来进一步过滤,所以我们将忽略可以使用 grep "1" * 代替此结构的事实。

对于 ls 命令,您可以使用 --quoting-style 选项强制给问题文件名称加上引号或进行转义。一个更好的解决方案(如果可用)是使用 xargs 命令的 -0 选项,这样会使用 null 字符 (\0) 来分隔输入参数。尽管 ls 没有提供 null 分隔文件名作为输出的选项,但许多命令都会这样做。

使用 xargs 和包含空格的文件名 首先将 text1 复制到 “text 1″,然后展示了一些结合使用包含空格的文件名列表和 xargs 的方式。这些示例仅用于演示概念,因为 xargs 很难掌握。具体地讲,如果一些文件名已包含换行符,最后一个将换行符转换为 null 的例子将不起作用。在本教程的下一部分中,将了解 一个使用 find 命令生成合适的 null 分隔输出的更稳健的解决方案。

使用 xargs 和包含空格的文件名
[ian@atticf22 lpi103-4]$ cp text1 "text 1"
[ian@atticf22 lpi103-4]$ ls *1 |xargs grep "1" # error
text1:1 apple
grep: text: No such file or directory
grep: 1: No such file or directory
[ian@atticf22 lpi103-4]$ ls --quoting-style escape *1
text1  text\ 1
[ian@atticf22 lpi103-4]$ ls --quoting-style shell *1
text1  'text 1'
[ian@atticf22 lpi103-4]$ ls --quoting-style shell *1 |xargs grep "1"
text1:1 apple
text 1:1 apple
[ian@atticf22 lpi103-4]$ # Illustrate -0 option of xargs
[ian@atticf22 lpi103-4]$ ls *1 | tr '\n' '\0' |xargs -0 grep "1"
text1:1 apple
text 1:1 apple

xargs 命令不会构建任意长度的命令。在 Linux 内核版本 2.26.3 之前,命令的最大长度是有限制的。对于一个包含大量具有长名称的文件的目录, rm somepath/* 这样的命令可能失败,并抛出一条表明参数列表太长的消息。在更低版本的 Linux 系统或可能仍有限制的 UNIX 系统上,了解如何使用 xargs 来处理这些情形可能很有用。

您可以使用 --show-limits 选项显示 xargs 的默认限制,使用 -s 选项将输出命令的大小限制到特定的最大字符数。请参阅手册页,了解这里未介绍的其他命令。

结合使用 find 命令和 -exec 选项或 xargs

在教程 “学习 Linux,101 :文件和目录管理 ” 中,您将学习如何使用 find 命令按名称、修改时间、大小或其他特征来查找文件。找到这样一组文件后,您通常希望对它们进行某种处理:删除它们,将它们复制到另一个位置,重命名它们,或者执行其他某种操作。现在看看 find-exec 选项,它的功能类似于使用 find 并将输出传输到 xargs

结合使用 find-exec
[ian@atticf22 lpi103-4]$ find text[12] -exec cat text3 {} \;
This is a sentence.  This is a sentence.  This is a sentence.
1 apple
2 pear
3 banana
This is a sentence.  This is a sentence.  This is a sentence.
9      plum
3      banana
10      apple

与您已学到的 xargs 用法相比,这里存在着一些不同:

  1. 必须 包含 {} 来标记文件名在命令中的位置。它不会自动添加到末尾。
  2. 您必须使用分号终止命令,而且分号必须转义;\;、’;’ 或 “;” 都可以使用。
  3. 该命令对每个输入文件执行一次。

尝试运行 find text[12] |xargs cat text3 来亲自了解这些区别。

现在,让我们返回到文件名包含空格的情况。在 结合使用 find-exec 和包含空格的文件名 中,您尝试结合使用 find-exec ,而不是 lsxargs

结合使用 find-exec 和包含空格的文件名
[ian@atticf22 lpi103-4]$ find . -name "*1" -exec grep "1" {} \;
1 apple
1 apple

目前为止,一切顺利。是否遗漏了什么?哪些文件包含 grep 找到的行?文件名遗漏了,因为 find 对每个文件调用 grep 一次,而且 grep 能够聪明地知道,如果您仅向它提供一个文件名,就不再需要它告诉您该文件是什么。

您可以使用 xargs 代替,但您已看到文件名包含空格的问题。我也暗示过,事实上 find 可以生成一个使用 null 作为分隔符的文件名列表,这需要使用 -print0 选项。现代 find 版本可能使用 + 符号代替分号来进行分隔,这会导致 find 在一次命令调用中传递尽可能多的名称,类似于 xargs 的工作方式。无需说,在这种情况下仅能使用 {} 一次,而且它必须是命令的最后一个参数。 结合使用 findxargs 和包含空格的文件名 展示了两种方法。

结合使用 findxargs 和包含空格的文件名
[ian@atticf22 lpi103-4]$ find . -name "*1" -print0 |xargs -0 grep "1"
./text1:1 apple
./text 1:1 apple
[ian@atticf22 lpi103-4]$ find . -name "*1" -exec grep "1" {} +
./text1:1 apple
./text 1:1 apple

一般而言,两种方法都有效,但具体采用哪种方法选择取决于个人风格。请记住,传输包含未受保护的空格或空白的内容可能导致问题,所以如果将输出传输到 xargs ,请使用 find-print0 选项,并使用 -0 选项告诉 xargs 要求采用以 null 分隔的输入。其他命令(包括 tar )也使用 -0 选项来支持 null 分隔的输入,所以您应始终对支持它的命令使用该选项,除非您确定输入列表不会导致问题。

最后介绍一下对文件列表的操作。在提交给批量操作(比如删除或重命名文件)之前,全面测试您的列表并非常仔细地测试您的命令始终是个不错的想法。拥有良好的备份也很重要。

拆分输出

最后,本节将简单讨论一下另一个命令。有时您可能想在屏幕上查看输出,同时保存某个副本供以后使用。尽管 可以 通过将命令输出重定向到窗口中的某个文件,然后使用 tail -fn1 命令在另一个屏幕中跟踪输出来实现此目的,但使用 tee 命令更容易。

可以将 tee 与管道结合使用。对标准输出而言,参数是一个(或多个)文件。 -a 选项会附加而不是覆盖文件。在之前对管道的讨论中您已看到,如果想要同时保存 stderr 和 stdout,需要在传输到 tee 之前将 stderr 重定向到 stdout。 使用 tee 拆分 stdout 展示了如何使用 tee 将输出保存到两个文件 f1 和 f2。

使用 tee 拆分 stdout
[ian@atticf22 lpi103-4]$ ls text[1-3]|tee f1 f2
text1
text2
text3
[ian@atticf22 lpi103-4]$ cat f1
text1
text2
text3
[ian@atticf22 lpi103-4]$ cat f2
text1
text2
text3

对流、管道和重定向的介绍到此就结束了。

本文翻译自:Learn Linux, 101: Streams, pipes, and redirects(2015-05-18)