Linux: encontre o primeiro resultado do caminho de pesquisa especificado

5

Se eu tiver uma lista de caminhos separada por dois pontos, muito parecida com $ PATH, mas não necessariamente com $ PATH.

Eu quero pesquisar essa lista para um nome de arquivo específico. No entanto, só quero o primeiro caminho correspondente.

Eu considerei os seguintes comandos do Linux:

  • which : funciona apenas para binário e funciona apenas com a variável $ PATH
  • whereis : trabalha com tipos específicos de arquivos e só funciona com a variável $ PATH
  • find : não suporta listas de caminhos separados por dois pontos e retorna vários resultados

Aqui estão algumas coisas que tentei:

  1. Eu tentei usar whereis pela seguinte estratégia

    env WHEREIS="'which whereis'" PATH="$MY_PATH_LIST" $WHEREIS "$TARGET_FILE"
    

    e isso quase funciona. No entanto, não parece retornar resultados para tipos de arquivos arbitrários. Também retorna vários resultados e em um formato inadequado.

  2. Eu consegui usar which para funcionar

    env WHICH="'which which'" PATH="$MY_PATH_LIST" $WHICH "$MY_TARGET_FILE"
    

    se houvesse uma opção de linha de comando para forçá-lo a permitir não executáveis.

  3. Tentei resolver o problema com find . Primeiro usei expressões regulares para expandir a lista de caminhos (substituo dois pontos por espaços). Então invoco encontrar e funciona corretamente. No entanto, ele procura todos os caminhos. Eu não consigo encontrar uma maneira de dizer para parar a busca mais cedo se encontrar um bom resultado.

    Eu consegui fazer isso funcionar

     find ${MY_PATH_LIST//[:]/ } -name "$MY_TARGET_FILE" | head -n 1
    

    mas demora muito para concluir, porque find ainda está fazendo uma pesquisa exaustiva.

    Eu preciso disso para executar mais rápido (sair no primeiro resultado), porque seria executado muitas vezes, com parâmetros diferentes.

Alguém tem uma solução melhor para sugerir?

Observe que, se tudo falhar, posso escrever uma solução não bash. Escreva agora, estou esperando por uma solução simples usando ferramentas existentes.

    
por Kevin A. Naudé 20.12.2012 / 12:18

2 respostas

3

Você poderia usar apenas um script que simplesmente testa ( -e ) a existência de um arquivo e pára quando o primeiro foi encontrado:

#!/bin/bash
[[ $# -gt 0 ]] || { echo "Usage: $0 <filename> [pathspec]" >&2 ; exit 1 ; }
if [[ $# -gt 1 ]] ; then
        P="$2"
else
        P="$PATH"
fi

IFS=:
for DIR in $P ; do
        if [[ -e "$DIR/$1" ]] ; then
                echo "$DIR/$1"
                exit 0
        fi
done

Exemplo:

$ ./search.sh 
Usage: ./search.sh <filename> [pathspec]

$ ./search.sh ls
/Users/danielbeck/bin/ls

$ ./search.sh pwd
/bin/pwd

$ ./search.sh ls /bin
/bin/ls

$ ./search.sh ls /usr/bin:/bin
/bin/ls
    
por 20.12.2012 / 12:27
0

Use head para obter o primeiro resultado do comando find.

find 'echo colon:separated:directories | sed 's/:/ /g'' -name filename | head -n1

Ou em uma função:

$ function findin { find 'echo $1 | sed 's/:/ /g'' -name $2 | head -n1; }
$ findin this:that:other filename
    
por 06.10.2014 / 23:46