在Linux操作系统中,命令行界面是一个强大的工具,它允许用户与系统进行高效的交互。重定向是命令行中一个非常重要的概念,它可以改变命令输入和输出的默认路径。通过重定向,用户可以将数据从一个程序传递到另一个程序,或者保存到文件中,这使得数据处理变得更加灵活和高效。
重定向是一种改变命令输入输出流的机制。默认情况下,大多数命令从标准输入(stdin,通常是键盘)读取数据,将结果输出到标准输出(stdout,通常是屏幕),并将错误消息输出到标准错误(stderr,也通常是屏幕)。重定向允许我们改变这些数据流的方向,从而可以将数据从一个文件或设备转移到另一个文件或设备。
重定向操作符允许我们改变这些通道的方向。例如,我们可以使用>
操作符将命令的输出保存到一个文件中,而不是打印到屏幕上。
在深入了解重定向之前,我们需要先理解标准输入、输出和错误这三个概念。每当我们执行一个命令时,它通常会从标准输入(stdin)读取数据,将结果输出到标准输出(stdout),并将错误信息输出到标准错误(stderr)。这三个通道默认情况下都是连接到我们的终端,即我们的屏幕和键盘。
每一个进程的fd目录下都会有0、1、2这三个文件描述符:
0
:标准输入流1
:标准输出流2
:标准错误流$ ll /proc/$$/fd
total 0
dr-x------ 2 vagrant vagrant 0 Dec 25 01:46 ./
dr-xr-xr-x 9 vagrant vagrant 0 Dec 25 01:46 ../
lrwx------ 1 vagrant vagrant 64 Dec 25 01:46 0 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64 Dec 25 01:46 1 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64 Dec 25 01:46 2 -> /dev/pts/0
$$
变量用于获取当前进场的PID。
>
符号用于将命令的输出重定向到一个文件,如果文件已存在,则会被覆盖。
$ echo "Hello, World!" > output.txt
$ echo "Hello, World!" 1> output.txt
$ cat output.txt
Hello, World!
命令中的1
是一个文件描述符,表示标准输出流,<
左边默认文件描述符的值就是1,所以可以省略。
>>
符号用于将命令的输出追加到一个文件的末尾,而不是覆盖它。
$ echo "Hello, World!" 1>> output.txt
$ echo "Hello, World!" >> output.txt
$ cat output.txt
Hello, World!
Hello, World!
Hello, World!
在使用重定向时,可能会遇到各种问题。例如,不小心使用>
而不是>>
可能会导致原有文件内容的丢失。为了避免这种情况,我们应该在执行命令前仔细检查所使用的重定向操作符。此外,学习如何使用Shell脚本中的条件语句来检查文件是否存在,也可以帮助我们避免数据覆盖的问题。
2>
符号用于将错误信息重定向到一个文件,如果文件已存在,则会被覆盖。
$ ls not_existing_file 2> error.txt
$ cat error.txt
ls: cannot access 'not_existing_file': No such file or directory
命令中的2
是一个文件描述符,表示标准错误流。
2>>
符号用于将错误信息追加到一个文件的末尾。
$ ls not_existing_file 2>> error.txt
$ cat error.txt
ls: cannot access 'not_existing_file': No such file or directory
ls: cannot access 'not_existing_file': No such file or directory
<
符号用于将文件的内容作为命令的输入。
$ read a < output.txt
$ echo $a
Hello, World!
read
指令读到换行符\n
就会停止,所以read a < output.txt
会将output.txt文件的第一行读取到并赋值给变量a。
将cat的标准输入重定向为test.txt
, 将其标准输出重定向为cat.out
。
$ cat 0< output.txt 1> cat.out
$ cat cat.out
Hello, World!
Hello, World!
Hello, World!
这样完成了将output.txt复制为cat.out文件,相当于cp命令。
stdout重定向到文件stdout.out
,stderr不重定向,默认还是会显示在shell屏幕上:
$ ls ./ no_exist_file 1> stdout.out
ls: cannot access 'no_exist_file': No such file or directory
stdout重定向到文件stdout.out
,stderr重定向到文件stderr.out
:
$ ls ./ no_exist_file 1> stdout.out 2> stderr.out
$ cat stdout.out
./:
cat.out
error.txt
ooxx.txt
output.txt
stderr.out
stdout.out
$ cat stderr.out
ls: cannot access 'no_exist_file': No such file or directory
可以同时重定向stdout和stderr到同一个文件。
&>
用于同时将标准输出和标准错误重定向到同一个文件。
$ ls ./ no_exist_file &> output.txt
$ cat output.txt
ls: cannot access 'no_exist_file': No such file or directory
./:
cat.out
error.txt
ooxx.txt
output.txt
stderr.out
stdout.out
或者使用更具体的描述符组合:
$ ls ./ no_exist_file 1> output.txt 2>&1
$ ls ./ no_exist_file 2> output.txt 1>&2
注意1>s.out
和2>&1
的顺序不能反过来,另外1
前面要加&
,否则会以为1
是一个普通的文件,而不是文件描述符。
1>s.out
和2>&1
的顺序伪代码解释:
// 伪代码
// 初始
fd1 = stdout
fd2 = stderr
// 1> output.txt 2>&1
fd1 = output.txt
fd2 = fd1 // fd2指向output.txt
// 2>&1 1> output.txt
fd2 = fd1 // fd2指向stdout
fd1 = output.txt
有时候,我们可能不想要命令的输出,这时可以将输出重定向到特殊的文件/dev/null
,这会丢弃所有重定向到它的数据。
$ command > /dev/null 2>&1
使用重定向也可以快速地创建空文件:
$ touch newfile.txt # 常规方法
$ > newfile.txt # 通过重定向创建空文件
Here文档是一种特殊的重定向方式,它允许你将多行输入直接在命令行中指定,而不是来自文件或键盘输入。
$ cat << EOF > output.txt
> first
> second
> EOF
$ cat output.txt
first
second
Here字符串是Here文档的简化版,它允许你将单行输入重定向到命令。
$ cat <<< "This is a single line"
重定向是Linux中一个非常强大的特性,它让用户能够灵活地控制命令的输入和输出。通过熟练使用重定向,可以在脚本编写和日常任务中实现更加复杂和高效的数据处理。