Encontre um diretório que contenha todos os arquivos da minha lista

2

Eu movi um arquivo, que faz uma referência a quatro outros arquivos com o mesmo diretório pai. E agora eu estou em estoque tentando descobrir qual diretório pai que é, pois há um número de arquivos com o mesmo nome no meu ambiente de compilação. Mas eu não quero me arriscar e copiar o arquivo errado. Então, eu quero saber se existe uma maneira de dizer ao comando de localização do Linux ou algum outro comando para me fornecer os resultados correspondentes a duas ou mais seqüências de caracteres. Por isso, só quero ver correspondências para localizações que contenham arquivos:

foo & bar & buz

Eu sempre posso canalizar isso para o grep para o diretório comum desejado, mas se houver uma maneira mais fácil, então eu adoraria. Algo como:

common_direcoty/foo & common_directory/bar & common_directory/buz 

Em outras palavras, estou procurando a cópia desses arquivos com um diretório comum. Eu não estou procurando o arquivo que corresponde ao nome sozinho.

Aqui está a saída do comando que me deu o que eu procurava:

sansari@ubuntu:~/WORKING_DIRECTORY$ find . -name io.h -exec sh -c '[ -e "${0%/*}/kernel.h" ] && [ -e "${0%/*}/init.h" ]' {} \; -print
./include/linux/io.h
sansari@ubuntu:~/WORKING_DIRECTORY/include/linux$ ls module.h
module.h
sansari@ubuntu:~/WORKING_DIRECTORY/include/linux$ ls kernel.h 
kernel.h
sansari@ubuntu:~/WORKING_DIRECTORY/include/linux$ ls init.h
init.h
sansari@ubuntu:~/WORKING_DIRECTORY/include/linux$ ls io.h
io.h
    
por user3326293 01.07.2015 / 07:33

3 respostas

2

Uma maneira é procurar por um dos nomes de arquivo (escolha o mais raro se você souber qual é) e filtrar as correspondências para reter apenas aquelas onde o outro arquivo existe.

find . -name foo -exec sh -c '[ -e "${0%/*}/bar" ] && [ -e "${0%/*}/buz" ] && echo "${0%/*}"' {} \;

Você pode usar o código de retorno do snippet de shell se desejar usar uma ação find , mas isso se aplicaria ao primeiro arquivo, não ao diretório. Por exemplo, o seguinte snippet imprime a saída do formulário ./path/to/foo :

find . -name foo -exec sh -c '[ -e "${0%/*}/bar" ] && [ -e "${0%/*}/buz" ]' {} \; -print

Se você precisar passar os nomes como argumentos:

find_multiple_files () {
  root=$1; shift
  name1=$2; shift
  find "$root" -name "$name1" -exec sh -c 'dir=${0%/*}; for x; do [ -e "$dir/$x" ] || exit 1; done; echo "$dir"' {} "$@" \;
}
find_multiple_files . foo bar buz

Uma abordagem alternativa é gerar listas de nomes e filtrá-los. Isso é um pouco mais incômodo e menos eficiente, mas tem a vantagem de poder alternar de find para locate se você tiver um índice de nomes de arquivos. Presumo que os nomes dos arquivos não contenham novas linhas.

locate foo |              # or: find -name foo
sed 's!/[^/]*$!!' |
xargs -I {} sh -c 'for x; do [ -e "$0/$x" ] || exit 1; done; echo "$0"' {} bar buz
    
por 01.07.2015 / 09:42
0

Eu não tenho conhecimento de nenhuma opção de busca que possa fazer tudo sozinha. Usando greps você pode conseguir isso - coloque todos os nomes de arquivo que você quer encontrar em um arquivo separado, digamos / tmp / files_to_find, com o seguinte padrão

No seu caso files_to_find seria

\/foo$
\/bar$
\/buz$

Em seguida, emita o seguinte comando

find root_dir_to_search_in | grep -f /tmp/files_to_find | xargs -I{} dirname {} | sort | uniq -c | grep 'wc -l /tmp/files_to_find | awk '{print $1}''
    
por 01.07.2015 / 08:00
0

Você deve ser capaz de agrupar find padrões com -or e -and para selecionar padrões diferentes. Eu não uso essas opções, mas é

$ find . \( -name foo -or -name bar -or -name buz \) -and -path '*/G/*'|9 mc
./G/buz ./G/bar ./G/foo

em que G = common_directory . Eu testei isso contra uma estrutura de arquivos

$ find . -name foo -or -name bar -or -name buz|9 mc
./G/buz ./G/bar ./G/foo ./F/buz ./F/bar ./F/foo

onde eu também tenho foo, bar e baz no diretório não_comum.

O comando 9 mc é o formatador de várias colunas do p9p, apenas para ajustar a saída.

    
por 01.07.2015 / 09:59

Tags