关于重定向的一些技巧
关于此的一些语法特殊性可能具有重要的行为。有一些关于重定向、STDERR、STDOUT 和参数ordering 的小示例。
1 - 覆盖还是追加?
符号> 表示重定向。
-
> 表示发送到作为一个完整的完整文件,如果存在则覆盖目标(请参阅后面的#3 中的noclobber bash 功能)。
-
>> 表示 除了发送之外 将附加到目标(如果存在)。
无论如何,如果文件不存在,就会创建该文件。
2 - shell 命令行 取决于顺序!!
为了测试这一点,我们需要一个简单的命令,它会在两个输出上发送一些东西:
$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
(当然,希望您没有名为/tnt 的目录;)。好吧,我们有它!
那么,让我们看看:
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1
$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory
最后一个命令行将STDERR 转储到控制台,这似乎不是预期的行为......但是......
如果你想对标准输出、错误输出或两者都做一些后过滤:
$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'
$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
请注意,本段中的最后一个命令行与上一段完全相同,我在前一段中写道似乎不是预期的行为(因此,这甚至可能是预期的行为)。
嗯,有一些关于重定向的小技巧,用于对两个输出进行不同的操作:
$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2 2>&1 | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan 7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory
注意:&9 描述符会因为) 9>&2 而自发出现。
附录:nota! 在新版本的 bash (>4.0) 中,有一个新功能和更性感的语法来执行此类操作:
$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory
最后对于这样的级联输出格式:
$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
1 O: drwxrwxrwt 118 root root 196608 Jan 7 12:29 /tmp
2 E: ls: cannot access /tnt: No such file or directory
附录:nota! 相同的新语法,两种方式:
$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
1 O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
2 E: ls: cannot access /tnt: No such file or directory
STDOUT 通过特定过滤器,STDERR 到另一个,最后合并的两个输出通过第三个命令过滤器。
3 - 关于noclobber 选项和>| 语法的一句话
关于覆盖:
虽然 set -o noclobber 指示 bash 不 覆盖任何现有文件,但 >| 语法可以让您突破这个限制:
$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:15 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:19 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:21 CET 2013
文件每次都会被覆盖,现在好了:
$ set -o noclobber
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
通过>|:
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:18:58 CET 2013
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:19:01 CET 2013
取消设置此选项和/或询问是否已设置。
$ set -o | grep noclobber
noclobber on
$ set +o noclobber
$ set -o | grep noclobber
noclobber off
$ date > $testfile ; cat $testfile
Mon Jan 7 13:24:27 CET 2013
$ rm $testfile
4 - 最后一招和更多...
对于从给定命令重定向 both 输出,我们看到正确的语法可能是:
$ ls -ld /tmp /tnt >/dev/null 2>&1
对于这种特殊情况,有一个快捷语法:&> ... 或>&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
注意:如果 2>&1 存在,1>&2 也是正确的语法:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
4b- 现在,我让你想想:
$ ls -ld /tmp /tnt 2>&1 1>&2 | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
$ ls -ld /tmp /tnt 1>&2 2>&1 | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
4c- 如果您对更多信息感兴趣
您可以通过点击阅读精美的手册:
man -Len -Pless\ +/^REDIRECTION bash
在bash 控制台中;-)