Как я могу выбрать один из результатов поиска и разрешить его открытие с помощью указанного приложения

У меня есть сценарий bash под названием findme , который кодируется следующим образом:

 #!/bin/bash locate -Abi '*\.'$1 $2 | grep --color=always -ni $2 | less -R 

Он ищет меня для всех файлов с указанным расширением файла (первый аргумент предоставлен скрипту), который имеет шаблон (следующий предоставленный аргумент) в своем имени файла.
Если я выполняю следующее:

 user@machine$ findme pdf classifi 

Он будет искать все pdf файлы с classifi в своем имени файла. Поэтому я могу получить что-то вроде следующего результата.

1: / home / user / Dropbox / SharedWithFriends / math / classifi cations2000.pdf
2: / home / user / Dropbox / SharedWithFriends / math / classifi cations2010.pdf

Возникает вопрос: «Можете ли вы дать мне код сценария bash, в котором после показа результатов мне нужно узнать число и зрителя, чтобы автоматизировать мою следующую работу?»

например, я бы хотел, если я войду:

 > 2 evince 

скрипт выполняет evince на 2 м элементе результата поиска, то есть , если это то, что я ввел в предыдущий результат поиска, он выполняет:

 evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf 

Ниже приведена вариация функции 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.

Обратите внимание, что ваш скрипт findme имеет несколько проблем:

  • Отсутствие двойных кавычек вокруг переменных подстановок
  • Вывод grep --color=always приводит к результатам, которые нельзя использовать при подстановке команд. Вам нужно, чтобы он проходил через less , но не пытайтесь повторно использовать его в скрипте.
  • grep и locate использовать другой синтаксис шаблонов, поэтому использование grep для окраски второго аргумента не всегда будет работать. Передача -r для locate заставляет его использовать регулярные выражения, но с синтаксисом Emacs, который немного отличается от синтаксисов, поддерживаемых grep.

В bash вы можете использовать mapfile для надежного 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" 

На основании решения, данного Джеффом Шаллером. Я нашел решение, я был бы рад, если бы получил ваши комментарии, чтобы сделать его лучше.

 #!/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