`< .` 和这个 `echo` 行为有什么特别之处吗?

`< .` 和这个 `echo` 行为有什么特别之处吗?

< .我想知道bash是否有什么特别之处

$ mail <destination> < .

发送一封空电子邮件而不是一个点并且

$ echo < .

与我以前所了解的关于 echo 的任何内容都不相符。

经过一番修改后,我想知道你如何解释echo以下内容的行为:

$ echo <=> 语法错误

$ echo < giberish=>错误:没有这样的文件或目录

$ echo < . giberish=>giberish

$ echo < .=> 空白

$ echo < "filenameInPWD"=> 空白

$ echo < "randomstring"=>错误:没有这样的文件或目录

答案1

如果你这样做

strace mail <dest> < .

你可以看到发生了什么(尽管你必须仔细观察)。在 Linux 系统上(如注释所述,如果目录读取成功,其他 Unix 系统的行为可能会有所不同),大约有 200 行输出,其中大部分是初始化,但有 3 行非常重要,在我的例子中是 3 行153、165 和 191:

...
read(0, 0x556829edb730, 8192)           = -1 EISDIR (Is a directory)
...
write(1, "No message, no subject; hope tha"..., 39No message, no subject; hope that's ok) = 39
...
write(4, "Date: Sat, 10 Oct 2020 23:19:22 "..., 212) = 212
...
exit_group(0)                           = ?
+++ exited with 0 +++

IOW,它尝试读取文件描述符 0 (其标准输入)并收到错误EISDIR:那是因为 shell 重定向.(即当前目录)作为其标准输入,并且read不允许读取目录。但邮件程序忽略了该错误,在其标准输出(文件描述符 1)上写入一条消息,表示没有消息,也没有主题提交给它,并且希望没问题,然后继续撰写邮件消息并将其写入文件描述符 4,大概是通过某种方式来发送消息的(消息由 212 个字符组成)。另请注意,程序以 0 状态退出(正常退出)。

cat如果你尝试用或做同样的事情tr,您会看到略有不同的结果。这些程序仍然尝试从文件描述符 0 读取并收到 EISDIR 错误 - 但它们确实这样做了不是忽略错误;相反,它们会退出并显示错误消息和非零状态:

$ strace cat < .
...
read(0, 0x7fc27daec000, 131072)         = -1 EISDIR (Is a directory)
write(2, "cat: ", 5cat: )                    = 5
write(2, "-", 1-)                        = 1
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Is a directory", 16: Is a directory)        = 16
write(2, "\n", 1
)                       = 1
munmap(0x7fc27daeb000, 139264)          = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

但处理方式没有区别< .:在这两种情况下,shell 将文件(当前目录)与执行程序的文件描述符 0(标准输入)相关联。但程序选择以不同的方式响应错误。就这样。

顺便说一句,@thanasisp 的答案是准确的,回答了你的大部分问题(即使它忽略了命令mail和 egtr或之间的细微差别cat,这就是我在这个答案中关注的内容)。

答案2

点代表当前目录,您可以看到在典型的常用命令中,如find .cp path/filename .,它的意思是“这里”。另外,点是该命令的同义词source,您可以通过键入 来看到它man .

在您的情况下,点被用作当前目录,因为此语法:

command < path/to/something

是重定向到命令的标准输入,如您在bash手册,而这个语法:

command < path/to/something argument

与上面相同,多了一个参数,如下所示:

command argument < path/to/something

因此,在您的情况下,echo不会抱怨,因为它根本不读取其标准输入,仅读取以下字符串并打印它。

您可以使用其他命令更好地看到这一点,例如tr仅读取其标准输入:

tr < . 'a' 'b' # or tr 'a' 'b' < .
tr: read error: Is a directory
tr < file 'a' 'b' # works.

相关内容