重定向运算符未按预期工作

Redirection operator is not working as expected

我的当前目录中有 2 个文件:/home/tushar/Desktop

file1.txt
file4.txt

所以当我按下命令时:

1. ls file{1..4}.txt

输出:

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory
file1.txt  file4.txt

现在我使用 :

将 stderr 和 stdout 重定向到一个文件 res.txt
2. ls file{1..4}.txt 1>res.txt 2>res.txt

res.txt :

file1.txt
file4.txt
ile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

上面我们可以看到文件res.txt.

中stderr的一些内容被省略了

现在我将命令更改为:

3. ls file{1..4}.txt 1>res.txt 2>&1

res.txt :

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory
file1.txt
file4.txt

以上命令完全相同,除了在第二个中我重定向了stderr,其中stdout使用文件描述符(&1)重定向。

现在我知道我应该使用 命令 附加模式打开 res.txt 如下所示:

4. ls file{1..4}.txt 1>>res.txt 2>&1
OR
5. ls file{1..4}.txt &> res.txt

但我担心的是:

Why the results of cmd 2 and cmd 3 are different ?

Why cmd 3 derived correct output even without using >> symbol but not cmd 2 ?

第二个问题:

因为 2>&1 意味着 fd 2 是 fd(文件描述符)1 的副本。然后 >>> open 1 (stdin) in append or in new/truncate 模式。所以他们描述了两个不同的操作,使用相同的 > 符号,只是因为:1-他们正在处理文件描述符(> 可以记住,而不是新的符号,例如涉及 $ , 2- 在添加这样的扩展之前是一个无效的语法,所以意义是唯一的。

问题1比较棘手。您独立地打开同一个文件两次,并且程序独立地看到它们,因此它们可能具有不同的缓存和优先级。一般来说:不要做 2,但如果你这样做,你必须刷新每一行的输出(并尽可能保持行短)。您可能会在日志记录中看到类似 2 的内容,但有时您也会看到两个程序混合并部分合并的输出。

我也不确定 2. 是否已定义,并且在所有 POSIX 兼容的 shell 中都可用。

在 cmd 3 中,您将 stderr 重定向到 res.txt。您会在 res.txt.

中找到错误消息

Why the results of cmd 2 and cmd 3 are different ?

因为 stdout 和 stderr 都覆盖了 res.txt 内容

Why cmd 3 derived correct output even without using >> symbol but not cmd 2 ?

cmd 3 并不总是有效,请参阅“How to redirect and append both stdout and stderr to a file with Bash?

 ls file{1..4}.txt >>res.txt 2>&1

这样会更好,因为文件是在附加模式下打开的,stderr 的文件描述符“2”将使用相同的模式。

更详细地回答第一个问题:当您 运行 ls file{1..4}.txt 1>res.txt 2>res.txt 时,它打开 res.txt 两次, 独立 。这意味着每个写入它的文件描述符对它在文件中的位置(它的偏移量或位置)有不同的想法。

当命令开始 运行ning 时,您有一个空文件,其中有两个文件描述符,这两个文件描述符都准备好写入文件的开头。到目前为止一切顺利。

ls 然后将其错误消息打印到标准输出,并将它们存储在文件中,从头开始。在这一点上我们还可以;该文件如下所示:

ls: cannot access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

之后,ls 开始将找到的文件写入标准输出。这里我们遇到了一个问题:stdout 文件描述符仍然指向文件的开头,所以它从头开始覆盖文件。它写入第一个文件名,给出:

file1.txtt access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

然后它写一个换行符,覆盖“cannot”中的“t”,给出:

file1.txt
 access 'file2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

然后写入下一个文件名,给出:

file1.txt
file4.txtfile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

然后是最后一个换行符,这次是在“file2”中的“f”上方:

file1.txt
file4.txt
ile2.txt': No such file or directory
ls: cannot access 'file3.txt': No such file or directory

...这就是您看到的最终结果。

基本上,这两个描述符都试图同时修改同一个文件,但没有正确协调(如果一个是另一个的副本,它们就会协调),所以它们互相绊倒.