Como posso escolher um dos resultados do `locate` e deixá-lo ser aberto com um aplicativo específico

Como posso escolher um dos resultados do `locate` e deixá-lo ser aberto com um aplicativo específico

Eu tenho um script bash chamado findme, que é codificado da seguinte forma:

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

Ele procura todos os arquivos com uma extensão de arquivo especificada (primeiro argumento fornecido ao script) que possui um padrão (o próximo argumento fornecido) em seu nome de arquivo.
Se eu executar o seguinte:

user@machine$ findme pdf classifi

Ele procurará todos pdfos arquivos classifiem seu nome de arquivo. Portanto, posso obter algo como o seguinte resultado.

1:/home/usuário/Dropbox/SharedWithFriends/math/classificarcations2000.pdf
2:/home/usuário/Dropbox/SharedWithFriends/math/classificarcações2010.pdf

A questão é: "Você pode me fornecer um código de script bash no qual, após mostrar os resultados, peça um número e um visualizador para automatizar meu próximo trabalho?"

por exemplo eu gostaria, se eu inserir:

> 2 evince

o script é executado evinceno 2segundo item do resultado da pesquisa,ou seja, se foi isso que eu digitei no resultado da pesquisa anterior, ele executa:

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

Responder1

Aqui está uma variação da sua findmefunção que obtém os resultados, mas em vez de usá grep-los para numerá-los ou lesspaginá-los, ela os lista em uma matriz interna e solicita a escolha do item e do programa.

#!/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]}"

Adicionei algumas citações ao seu script original para lidar melhor com espaços em nomes de arquivos ou até mesmo com parâmetros grep. Ajustei a readarraychamada para que os resultados comecem no índice 1 em vez de 0, para que corresponda à numeração do grep.

Responder2

Observe que seu findmescript tem alguns problemas:

  • Faltando aspas duplas em torno de substituições de variáveis
  • A saída de grep --color=alwaysproduz resultados que não podem ser usados ​​em uma substituição de comando. Você precisa passar less, mas não tente reutilizá-lo em um script.
  • grep e localizar usam sintaxe de padrão diferente, portanto, usar greppara colorir o segundo argumento nem sempre funcionará. Passar -rpara locatefaz com que ele use regexps, mas com a sintaxe do Emacs que é um pouco diferente das sintaxes suportadas pelo grep.

No bash, você pode usarmapfilepara colocar algumas linhas de forma confiável em uma matriz. Combine-o comsubstituição de processopara usar a saída de um comando. Em seguida, imprima esse array e leia a entrada do usuário.

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
}

Uma interface alternativa seria definir os parâmetros posicionais. É um pouco complicado, porque você não pode alterar os parâmetros posicionais de uma função, mas há ummaneira indireta de fazer isso no bashusando um alias e fornecendo um script. Cuidado ao citar.

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
}

Uso:

findrun pdf classifi
evince "$2"

Responder3

Baseado na solução dada por Jeff Schaller. Encontrei uma solução, ficaria feliz se recebesse seus comentários, para melhorar.

#!/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]}"

Parece uma resposta simples (até a complexidade dos tópicos).

Mas não é suficiente se os resultados forem superiores a um determinado número! Nesse caso, precisamos de algo como moreouless

informação relacionada