Как выбрать один из результатов поиска `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/user/Dropbox/SharedWithFriends/math/классификацияcations2000.pdf
2:/home/user/Dropbox/SharedWithFriends/math/классификациякатионы2010.pdf

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

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

> 2 evince

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

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 используют разный синтаксис шаблонов, поэтому использование grepto color второго аргумента не всегда будет работать. Передача -rto locateзаставляет его использовать регулярные выражения, но с синтаксисом 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

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

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

Связанный контент