Encontre um arquivo específico no antepassado mais próximo do diretório de trabalho atual

2

Gostaria de encontrar uma maneira de encontrar um determinado arquivo procurando para cima na estrutura de diretórios, em vez de pesquisar recursivamente por meio de diretórios filhos.

Há um módulo de nó que parece fazer exatamente o que eu quero , mas eu não quero depender na instalação de JavaScript ou pacotes como esse. Existe um comando shell para isso? Uma maneira de fazer find fazer isso? Ou uma abordagem padrão que eu não consegui encontrar no Google?

    
por iconoclast 02.07.2016 / 01:07

3 respostas

3

Um simples loop de verificação do diretório atual e, se não for encontrado, então remover o último componente funcionaria

#!/bin/bash

wantfile="$1"

dir=$(realpath .)

found=""

while [ -z "$found" -a -n "$dir" ]
do
  if [ -e "$dir/$wantfile" ]
  then
    found="$dir/$wantfile"
  fi
  dir=${dir%/*}
done

if [ -z "$found" ]
then
  echo Can not find: $wantfile
else
  echo Found: $found
fi

Por exemplo, se esta for a árvore de diretórios:

$ find /tmp/A
/tmp/A
/tmp/A/good
/tmp/A/good/show
/tmp/A/good/show/this
/tmp/A/B
/tmp/A/B/C
/tmp/A/B/C/thefile
/tmp/A/B/C/D
/tmp/A/B/C/D/E
/tmp/A/B/C/D/E/F
/tmp/A/B/C/D/E/F/srchup

$ pwd      
/tmp/A/B/C/D/E/F

$ ./srchup thefile
Found: /tmp/A/B/C/thefile

Podemos ver que a pesquisa subiu na árvore até encontrar o que procurávamos.

    
por 02.07.2016 / 01:20
3

Uma maneira de fazer isso:

#! /bin/sh
dir=$(pwd -P)
while [ -n "$dir" -a ! -f "$dir/$1" ]; do
    dir=${dir%/*}
done
if [ -f "$dir/$1" ]; then printf '%s\n' "$dir/$1"; fi

Substitua pwd -P por pwd -L se você quiser seguir links simbólicos em vez de verificar diretórios físicos.

    
por 02.07.2016 / 06:57
1

Esta é uma tradução direta do algoritmo find-config em comandos shell genéricos (testados no bash , ksh e zsh), onde eu uso um código de retorno de 0 para significar sucesso e 1 para indicar NULL / falha.

function findconfig {
  # from: https://www.npmjs.com/package/find-config#algorithm
  # 1. If X/file.ext exists, return it. STOP
  # 2. If X/.dir/file.ext exists, return it. STOP
  # 3. If X has a parent directory, change X to parent. GO TO 1
  # 4. Return NULL.
  #

  [ -f "$1" ] && echo "$PWD/$1" && return 0
  [ -f ".dir/$1" ] && echo "$PWD/.dir/$1" && return 0
  [ $PWD = "/" ] && return 1
  # a subshell so that we don't affect the caller's $PWD
  (cd .. && findconfig "$1")
}

Exemplo de execução, com a configuração roubada copiada e estendida de Stephen Harris ' s resposta:

$ mkdir -p ~/tmp/iconoclast
$ cd ~/tmp/iconoclast
$ mkdir -p A/B/C/D/E/F A/good/show A/B/.dir
$ touch A/good/show/this A/B/C/D/E/F/srchup A/B/C/thefile A/B/.dir/anotherfile
$ cd A/B/C/D/E/F
$ findconfig thefile
/home/jeff/tmp/iconoclast/A/B/C/thefile
$ echo $?
0
$ findconfig foobar
$ echo $?
1
$ findconfig anotherfile
/home/jeff/tmp/iconoclast/A/B/.dir/anotherfile
$ echo $?
0
    
por 02.07.2016 / 16:57