1、标准的输入(stdin)、标准的输出(stdout)及标准错误(stderr)
(1) 默认情况下始终有3个"文件"(文件描述符)处于打开状态。
标准的输入: stdin (键盘)
标准的输出: stdout (屏幕)
标准错误输出:stderr (错误消息输出到屏幕上).
(2)文件描述符
一个文件描述符说白了就是文件系统为了跟踪这个打开的文件而分配给它的一个数字. 也可以的将其理解为文件指针的一个简单版本. 与C中的文件句柄的概念相似.
标准输入
文件描述符是0
标准输出
文件描述符是1
标准错误输出
文件描述符是2
- 在LINUX系统中,系统为每一个打开的文件分配一个文件描述符,每个文件都与一个文件描述符相关联。
- 文件描述符是一个数字,便于LINUX系统跟踪打开的文件。
- 一般LINUX系统文件描述符有1024的限制,可以使用命令ulimit -n 查看限制。(绝大多数情况下是够用的。)
- 在LINUX下,可以使用exec来指定打开文件的文件描述符。
- 注:使用文件描述符5可能会引起问题. 当Bash使用exec创建一个子进程的时候, 子进程会继承fd5. 最好还是不要去招惹这个特定的fd.
2、I / o 重定向
这3个文件和其他打开的文件都可以被重定向. 对于重定向简单的解释就是捕捉一个文件, 命令, 程序, 脚本, 或者甚至是脚本中的代码块的输出, 然后将这些输出作为输入发送到另一个文件, 命令, 程序, 或脚本中。
(1)基本重定向
1)大于号“ >” , 输出重定向
# 重定向stdout到一个文件.
# 如果没有这个文件就创建, 否则就覆盖.
例:
① ls -lR > dir-tree.list
# 创建一个包含目录树列表的文件.
② : > filename
# > 会把文件"filename"截断为0长度.
# 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
# : 是一个占位符, 不产生任何输出.
③ > filename
# > 会把文件"filename"截断为0长度.
# 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
# (与上边的": >"效果相同, 但是在某些shell下可能不能工作.)
2) 双大于号“>>”
# 重定向stdout到一个文件.
# 如果文件不存在, 那么就创建它, 如果存在, 那么就追加到文件后边.
3)小于号“<”
#输入重定向
例:
wc -l < script.log
#输出script.log的行数
4) 单行重定向命令(只会影响它们所在的行):
# --------------------------------------------------------------------
有下列用法,与命令与一起,用
1>filename
# 重定向stdout到文件"filename".
1>>filename
# 重定向并追加stdout到文件"filename".
2>filename
# 重定向stderr到文件"filename".
2>>filename
# 重定向并追加stderr到文件"filename".
&>filename
# 将stdout和stderr都重定向到文件"filename".
例:
LOGFILE=script.log
echo "This statement is sent to the log file, \"$LOGFILE\"." 1>$LOGFILE
echo "This statement is appended to \"$LOGFILE\"." 1>>$LOGFILE
echo "This statement is also appended to \"$LOGFILE\"." 1>>$LOGFILE
echo "This statement is echoed to stdout, and will not appear in \"$LOGFILE\"."
# 每行过后, 这些重定向命令会自动"reset".
注:注意理解行的命令执行结果
2>&1
# 重定向stderr到stdout.
# 得到的错误消息与stdout一样, 发送到一个地方.
i>&j
# 重定向文件描述符i 到 j.
# 指向i文件的所有输出都发送到j中去.
>&j
# 默认的, 重定向文件描述符1(stdout)到 j.
# 所有传递到stdout的输出都送到j中去.
0< FILENAME
< FILENAME
# 从文件中接受输入.
# 与">"是成对命令, 并且通常都是结合使用.
#
# grep search-word <filename
[j]<>filename
# 为了读写"filename", 把文件"filename"打开, 并且分配文件描述符"j"给它.
# 如果文件"filename"不存在, 那么就创建它.
# 如果文件描述符"j"没指定, 那默认是fd 0, stdin.
例:
# 这种应用通常是为了写到一个文件中指定的地方.
echo 1234567890 > File # 写字符串到"File".
exec 3<> File # 打开"File"并且给它分配fd 3.
read -n 4 <&3 # 只读4个字符.
echo -n . >&3 # 写一个小数点.
exec 3>&- # 关闭fd 3.
cat File # ==> 1234.67890
# 随机存储.
n<&-
关闭输入文件描述符n.
0<&-, <&-
关闭stdin.
n>&-
关闭输出文件描述符n.
1>&-, >&-
关闭stdout.
5)重定向的组合
① CMD 1> file1 2> file2 : 将输出重定向到 file1中,并把标准错误重定向到 file2中。
② CMD < file1 > file2 : 以 file1文件作为 CMD命令的标准输入,以 file2文件作为标准输出。
举例: find / -name "*.tmp" -print 1>find.out 2>find.err
# 把 find的搜索结果写到文件 find.out中,而把 find命令的错误信息(比如没有足够权限搜索某些目录)写到文件find.err中
cat <1.txt >2.txt
#实际是将 1.txt的内容写到2.txt,等效于文件复制
③ CMD > filename 2>&1 : 把标准输出和标准错误一起重定向到一个文件中
④ CMD >> filename 2>&1 : 把标准输出和标准错误一起重定向到一个文件中(追加)
举例: grep "test" * > grep.out 2>&1
#在当前目录下所有文本文件中搜索字符串"test",将标准输出和标准错误一起输出到文件grep.out中
说明:CMD > filename 2>&1 实际上可以看作2 部分,"> filename"(重定向标准输出)和"2>&1"(把标准错误重定向到标准输出)。
⑤cmd 2>&1 1>filename 实际上可以看作2 部分,"2>&1"(把标准错误重定向到标准输出)和"1>filename"(把标准错误输出重定向到filename)。这样做的结果是,标准错误在屏幕输出,文件中是标准输出的内容
例: