wes*_*wes 4 pipe xargs shell-script command-substitution
我试图找到一个文件,find
然后将找到的路径传递给sqlite3
. sqlite>
如果我的命令是以下形式,我只会进入提示:
sqlite3 `find . -type f -iname "*.db" | head -n1`
Run Code Online (Sandbox Code Playgroud)
但这些表格不起作用:
find . -type f -iname "*.db" | head -n1 | xargs sqlite3
find . -type f -iname "*.db" | head -n1 | xargs -I% sh -c 'sqlite3 %;'
Run Code Online (Sandbox Code Playgroud)
为什么后面的命令什么都不做?
在:
... | xargs cmd
Run Code Online (Sandbox Code Playgroud)
根据实现,cmd
的标准输入要么是 要么是/dev/null
那个管道。它不能是外部标准输入,因为它因管道而丢失。
$ echo /proc/self/fd/0 | gnu-xargs ls -ld
lr-x------ 1 me me 64 Dec 11 22:04 /proc/self/fd/0 -> /dev/null
$ echo /proc/self/fd/0 | busybox-or-solaris-...-xargs ls -ld
lr-x------ 1 me me 64 Dec 11 22:04 /proc/self/fd/0 -> pipe:[99839]
Run Code Online (Sandbox Code Playgroud)
无论哪种情况,sqlite3
都无法读取您的任何输入。
这:
sqlite3 `find . -type f -iname "*.db" | head -n1`
Run Code Online (Sandbox Code Playgroud)
command 获取由 返回的第一个文件路径的第一行,find
根据 将其拆分$IFS
,对它们执行通配符,并将结果单词作为不同的参数传递给 sqlite3。那意义不大。
使用 GNU find
(可能是您使用的,因为您正在使用-iname
):
sqlite3 "$(find . -type f -iname "*.db" -print -quit)"
Run Code Online (Sandbox Code Playgroud)
我们使用-exit
to tellfind
在打印第一个找到的文件后退出。我们使用现代形式的命令替换$(...)
,并通过引用命令替换来跳过 split+glob 部分(没有意义)。
您还可以使用(仍然是 GNU 特定的):
find . -type f -iname '*.db' \( -exec sqlite3 {} \; -o -true \) -quit
Run Code Online (Sandbox Code Playgroud)
(尽管您会失去 的退出状态sqlite3
)。
与zsh
:
setopt extendedglob # best in ~/.zshrc
sqlite3 ./**/*.(#i)db(D.[1])
Run Code Online (Sandbox Code Playgroud)