如何選擇“locate”的結果之一併讓它用指定的應用程式打開

如何選擇“locate”的結果之一併讓它用指定的應用程式打開

我有一個名為 的 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上執行,2IE,如果這是我在之前的搜尋結果中輸入的內容,它將執行:

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第二個參數著色並不總是有效。傳遞-rtolocate使其使用正規表示式,但 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]}"

這看起來像是一個簡單的答案(取決於主題的複雜性)。

但如果結果超過一定數量就不夠好!在這種情況下,我們需要類似moreless

相關內容