
我有一個名為 的 bash 腳本findme
,其編碼如下:
#!/bin/bash
locate -Abi '*\.'$1 $2 | grep --color=always -ni $2 | less -R
它為我搜尋具有指定文件副檔名(提供給腳本的第一個參數)的所有文件,這些文件的文件名中具有模式(下一個提供的參數)。
如果我執行以下命令:
user@machine$ findme pdf classifi
它將搜尋檔案名稱中pdf
帶有 的所有檔案。classifi
所以我可能會得到類似下面的結果。
1:/home/用戶/Dropbox/SharedWithFriends/math/分類cations2000.pdf
2:/home/user/Dropbox/SharedWithFriends/math/分類陽離子2010.pdf
問題是: “你能給我一個 bash 腳本代碼,在顯示結果後詢問我一個號碼和一個查看器,以自動化我的下一項工作嗎?”
例如,如果我輸入:
> 2 evince
該腳本在搜尋結果的第 nd 項evince
上執行,2
IE,如果這是我在之前的搜尋結果中輸入的內容,它將執行:
evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf
答案1
findme
這是提取結果的函數的變體,但它不是使用grep
對結果進行編號或less
分頁,而是從內部數組中列出它們,然後提示您選擇項目和程序。
#!/usr/bin/env bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2" | grep --color=always -i "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s\n" $i "${results[i]}"
done
read -p "> " item program
$program "${results[item]}"
我在原始腳本中添加了一些引用,以更好地處理檔案名稱中的空格,甚至 grep 參數。我調整了readarray
調用,使結果從索引 1 而不是 0 開始,這樣它就對應於 grep 的編號。
答案2
請注意,您的findme
腳本有一些問題:
- 變數替換周圍缺少雙引號
- 的輸出
grep --color=always
產生不能在命令替換中使用的結果。您需要它通過less
,但不要嘗試在腳本中重複使用它。 - grep 和locate 使用不同的模式語法,因此使用
grep
第二個參數著色並不總是有效。傳遞-r
tolocate
使其使用正規表示式,但 Emacs 語法與 grep 支援的語法略有不同。
在 bash 中,您可以使用mapfile
可靠地將一些行填入數組中。將其與流程替代使用命令的輸出。然後列印該數組並讀取使用者的輸入。
findrun () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2"
if read -a cmd; then
set -- "${cmd[@]}"
set -- "$@" "${search_hits[$1]}"
shift
"$@"
fi
}
另一個介面是設定位置參數。這有點棘手,因為您無法更改函數中的位置參數,但是有一個在 bash 中以迂迴的方式做到這一點透過使用別名並取得腳本。謹防引用。
alias findrun='. <(echo findrun_prepare \"\$@\"; echo set -- "\"\${search_hits[@]}\"")'
findrun_prepare () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2" >&2
}
用法:
findrun pdf classifi
evince "$2"
答案3
基於 Jeff Schaller 給出的解決方案。我找到了解決方案,如果收到您的意見,我會很高興,以使其變得更好。
#!/bin/bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s" $i "${results[i]}" | grep --color=always -i "$2"
done
read -p "> " item program
$program "${results[item]}"
這看起來像是一個簡單的答案(取決於主題的複雜性)。
但如果結果超過一定數量就不夠好!在這種情況下,我們需要類似more
或less