Shell-Scriptcmd2
cmd2 cmd1
與 cmd1 |xargs cmd2
我試圖找到一個文件,
find
然後將找到的路徑傳遞給sqlite3
.sqlite>
如果我的命令是以下形式,我只會進入提示:sqlite3 `find . -type f -iname "*.db" | head -n1`
但這些形式不起作用:
find . -type f -iname "*.db" | head -n1 | xargs sqlite3 find . -type f -iname "*.db" | head -n1 | xargs -I% sh -c 'sqlite3 %;'
為什麼後面的命令什麼都不做?
在:
... | xargs cmd
根據實現,
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]
無論哪種情況,
sqlite3
都無法讀取您的任何輸入。這:
sqlite3 `find . -type f -iname "*.db" | head -n1`
命令獲取由返回的第一個文件路徑的第一行,
find
根據 對其進行拆分,$IFS
對它們執行萬用字元,並將生成的單詞作為不同的參數傳遞給 sqlite3。這沒什麼意義。使用 GNU
find
(可能是您使用以來所使用的-iname
):sqlite3 "$(find . -type f -iname "*.db" -print -quit)"
我們
-exit
用來告訴find
在列印第一個找到的文件後退出。我們使用命令替換的現代形式$(...)
,並通過引用命令替換來跳過 split+glob 部分(這沒有意義)。您還可以使用(仍然是 GNU 特定的):
find . -type f -iname '*.db' \( -exec sqlite3 {} \; -o -true \) -quit
(儘管您將失去 的退出狀態
sqlite3
)。與
zsh
:setopt extendedglob # best in ~/.zshrc sqlite3 ./**/*.(#i)db(D.[1])