Bash 允许以这种方式从另一个命令管道到标准输入......
$ ls /bin/aud* | cat
/bin/audacity
/bin/audiocompose
/bin/audiosend
...
...还有这样的方式:
$ cat <(ls /bin/aud*)
/bin/audacity
/bin/audiocompose
/bin/audiosend
...
然而,当我尝试使用相同的模式向 SQLite 发送查询时,我从第一个表单中得到了这个......
$ echo "select count(*) from urls;" | \
sqlite3 ~/.config/google-chrome/Default/History
5983
...但是第二个出现这个错误:
$ sqlite3 ~/.config/google-chrome/Default/History \
<(echo "select count(*) from urls;")
Error: near "/": syntax error
这令人惊讶... SQL 语句没有被 shell 插入或弄乱:
$ echo "select count(*) from urls;"
echo "select count(*) from urls;"
这与两者无关echo
- 它绝对可以用于重定向:
$ cat <(echo Foo)
Foo
我能想到的是,不知何故,数据库文件的路径被误解并作为 SQL 语句传入...(这是唯一包含“/”的地方 - “/ 附近的语法错误”的唯一解释)。
但为什么呢?有任何想法吗?
答案1
I/O 重定向的第二种形式 ( <(cmd)
) 的行为方式与第一种形式 ( cmd | other-cmd
) 不同。
第一个将 的输出连接cmd
到 的输入other-cmd
,但第二个替换路径/dev/fd
或命名管道命令的路径。的标准输出绑定到该管道的另一端,但这仅与从标准输入或文件路径读取的cmd
命令等效。行为并非如此,因此它暴露了两种形式的 I/O 重定向之间的差异。cat
sqlite3
sqlite3
期望数据库路径后面是可选的 SQL 语句,因此它尝试将此替换路径解析为 SQL 并失败。
顺便说一句,这意味着您根本不需要 I/O 重定向。该命令比您尝试过的任何一种形式都更有效地完成您想要的操作:
$ sqlite3 ~/.config/google-chrome/Default/History "select count(*) from urls"
sqlite3
请注意,在将单个 SQL 语句作为命令行参数传递时,不需要语句终止分号。
答案2
$ echo <(echo "hi")
/dev/fd/63
/dev/fd/63
不是 SQL,因此sqlite3
失败并显示指示的错误消息。cat
相比之下,它非常擅长读取文件(或者也可以从标准输入读取)。创建的构造的命名管道或/dev/fd
文件<(list)
不是标准输入。