Como posso escolher um dos resultados de 'locate' e deixá-lo ser aberto com um aplicativo especificado

1

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 por mim por todos os arquivos com uma extensão de arquivo especificada (primeiro argumento fornecido ao script) que tem 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 os arquivos pdf com classifi em seu nome de arquivo. Então eu posso conseguir algo como o seguinte resultado.

1:/home/user/Dropbox/SharedWithFriends/math/classifications2000.pdf
2:/home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf

A pergunta é: "Você pode me dar um código de script que mostre os resultados e me peça um número e um visualizador, para automatizar meu próximo trabalho?"

por exemplo, eu gostaria, se eu digitar:

> 2 evince

o script executa evince no item 2 nd do resultado da pesquisa, i.e. , se é isso que eu digitei no resultado da pesquisa anterior, ele executa:

evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf
    
por texinfo 02.11.2016 / 18:42

3 respostas

2

Aqui está uma variação da função findme que obtém os resultados, mas em vez de usar grep para numerá-los ou less para paginá-los, lista-os a partir de uma matriz interna e solicita o item e escolha 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]}"

Eu adicionei algumas citações ao seu script original para lidar melhor com espaços em nomes de arquivos, ou mesmo com parâmetros grep. Eu ajustei a chamada readarray para que os resultados começassem no índice 1 em vez de 0, de modo que correspondesse à numeração do grep.

    
por 02.11.2016 / 20:59
2

Observe que seu script findme tem alguns problemas:

  • Faltam aspas duplas em torno de substituições de variáveis
  • A saída de grep --color=always produz resultados que não podem ser usados em uma substituição de comando. Você precisa que ele passe por less , mas não tente reutilizá-lo em um script.
  • grep e locate usam uma sintaxe de padrão diferente, portanto, usar grep para colorir o segundo argumento nem sempre funcionará. Passar -r para locate faz com que use regexps, mas com a sintaxe Emacs, que é um pouco diferente das sintaxes que o grep suporta.

No bash, você pode usar mapfile para preencher algumas linhas em uma matriz. Combine-o com a substituição de processos para usar a saída de um comando. Em seguida, imprima essa matriz 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á um usando um alias e sourcing um script. Cuidado com as citações.

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"
    
por 03.11.2016 / 01:40
0

Baseado na solução dada por Jeff Schaller. Eu encontrei uma solução, eu ficaria feliz se eu receber seus comentários, para torná-lo melhor.

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

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

Mas não está bem o suficiente se os resultados forem mais do que um certo número! Nesse caso, precisamos de algo como more ou less

    
por 03.11.2016 / 00:04