< .
我想知道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.