AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 736178
Accepted
alexis
alexis
Asked: 2023-02-21 03:05:24 +0800 CST2023-02-21 03:05:24 +0800 CST 2023-02-21 03:05:24 +0800 CST

Pesquisa semelhante a um caminho para um arquivo

  • 772

Basicamente, estou tentando obter algo semelhante ao command search with $PATH, mas com uma lista diferente de diretórios e o arquivo que estou procurando não é executável.

A lista de diretórios é fixa (posso empacotá-la em uma variável no mesmo formato de PATH, ou qualquer outro), e não quero descer em subdiretórios. Lembro-me vagamente de que o bash completetem uma opção para isso, mas li a seção e não consigo identificá-la. Estou perto?

Talvez algo assim (supondo que o arquivo esteja em ~/lib):

> filepath -p ".:/etc:$HOME/lib:$HOME/bin" foo
/home/alexis/lib/foo

Em outras palavras, estou procurando por algo como whichou which -a, o que for mais fácil, mas não deve se limitar a executáveis ​​(e não deve pesquisar apenas $PATH, mas posso contornar isso ;-)).

bash
  • 3 3 respostas
  • 70 Views

3 respostas

  • Voted
  1. Freddy
    2023-02-21T15:00:55+08:002023-02-21T15:00:55+08:00

    Você pode usar uma função bash como wrapper para GNU find:

    filepath () {
        local fp_path=${FP_PATH:-".:/etc:$HOME/lib:$HOME/bin"} fpath fquit=-quit
        local usage="usage: filepath [-a] [-p path[:path...]] expr"
    
        OPTIND=1
        while getopts :ap: opt; do
            case $opt in
                a)  fquit=
                    ;;
                p)  fp_path=$OPTARG
                    ;;
                *)  echo "$usage" >&2
                    return 1
            esac
        done
        shift $((OPTIND-1))
    
        if [ -z "$1" ]; then
            echo "$usage" >&2
            return 1
        fi
    
        IFS=: read -r -a fpath <<<"$fp_path"
        find "${fpath[@]}" -maxdepth 1 \( -type f -o -type l \) -name "$1" -print $fquit 2>/dev/null
    }
    

    O caminho de pesquisa padrão é definido na primeira linha da função, use :como separador. Ele pode ser substituído por variável de ambiente FP_PATHou opção -p.
    findsai depois de imprimir o primeiro resultado, a menos que a opção -aseja usada. A pesquisa é limitada a arquivos regulares e links simbólicos, ajuste as opções conforme necessário.

    Exemplos:

    $ mkdir -p ~/bin /tmp/etc
    $ touch ~/bin/foo /tmp/foo /tmp/etc/foo
    $ filepath
    usage: filepath [-a] [-p path[:path...]] expr
    
    $ filepath -a -p /tmp:/tmp/etc 'fo*'
    /tmp/foo
    /tmp/etc/foo
    
    $ filepath -p /tmp:/tmp/etc 'fo*'
    /tmp/foo
    
    $ FP_PATH=/tmp filepath foo
    /tmp/foo
    
    $ filepath foo
    /home/freddy/bin/foo
    
    • 1
  2. Best Answer
    phuclv
    2023-02-21T18:05:57+08:002023-02-21T18:05:57+08:00

    findjá suporta vários caminhos de pesquisa

    find . /etc ~/lib ~/bin -maxdepth 1 -name '*foo*'
    

    Como alternativa, use fdo que é significativamente mais rápido, com muito mais recursos e mais bonito do que encontrar

    fd --max-depth=1 foo . /etc ~/lib ~/bin
    
    • 1
  3. roaima
    2023-02-22T01:06:28+08:002023-02-22T01:06:28+08:00

    Se quiser armazenar a lista de diretórios em um array ( bash), você pode usar um código como este:

    # Maybe in ~/.bashrc
    filefindlist=(. /etc "$HOME/lib" "$HOME/bin" src/*)
    
    filefind() {
        local ff
        for ff in "${filefindlist[@]}"
        do
            if [ -d "$ff" ] && [ -f "$ff/$1" ]
            then
                printf '%s\n' "$ff/$1"
                return 0
            fi
        done
        return 1
    }
    

    Uso

    filefind program.c
    

    Observe que quaisquer variáveis ​​e globs de shell - curingas - serão avaliados no momento em que a matriz filefindlistfor definida. Portanto, se você tiver src/onee posteriormente criar src/two, src/*terá expandido apenas para src/one. Da próxima vez que você definir a matriz, porém, ela incluirá src/onee src/two.

    Se você deseja uma implementação exata de sua sugestão na pergunta, algo assim pode funcionar:

    filefind() {
        local fl="$FILEFINDLIST" fp ff
    
        [ "$1" = '-p' ] && fl="$2" && shift 2    # Override default search list
        readarray -d: -t fp <<<"$fl"             # Convert to array
    
        for ff in "${fp[@]}"
        do
            if [ -d "$ff" ] && [ -f "$ff/$1" ]
            then
                printf '%s\n' "$ff/$1"
                return 0                         # Only print first match
            fi
        done
        return 1
    }
    

    Uso

    FILEFINDLIST='.:$HOME/lib:$HOME/bin'
    
    filefind -p ".:/etc:$HOME/lib:$HOME/bin" program.c
    filefind program.c
    
    • 0

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve