Passa uma lista de diretórios armazenados em um arquivo para encontrar o comando

1

De um diretório e seus subdiretórios, encontra-se todos os arquivos .c

find /user/home/me/tests/ -name \*\.c

Agora, uma lista de diretórios é armazenada em um arquivo 'list_of_dir'

/user/home/me/test1
/user/home/me/test2
/user/home/me/test3
...

Como alguém pode alimentá-los ao comando find para encontrar todos os arquivos .c neles e seus subdiretórios?

Obrigado antecipadamente.

Edit: o shell padrão para mim é o tcsh.

    
por jianz 17.01.2018 / 00:24

5 respostas

2

Se você tiver uma lista de diretórios separada por nova linha no arquivo list_of_dir e quiser passar essa lista para find com segurança, sem divisão de palavras ou expansão de nome de caminho e sem exceder os limites de comprimento de linha, use xargs (assumindo aqui a implementação do GNU para suas opções -d e -r ):

xargs -r -d'\n' -I{} find {} -name '*.c' <list_of_dir

Para ser verdadeiramente seguro, deve-se usar uma lista de diretórios separada por NUL, não uma lista separada por nova linha. Se list_of_dir0 contiver uma lista de diretórios separada por NUL, use:

xargs -r -0 -I{} find {} -name '*.c' <list_of_dir0

Como funciona

  • -r diz ao xargs para não executar find , a menos que a lista de diretórios esteja vazia.

  • -0 diz ao xargs para esperar uma lista separada por NUL na entrada. Esta é a alternativa mais segura para -d'\n' , que diz ao xargs para esperar uma lista separada por nova linha.

  • - I{} diz ao xargs para colocar os diretórios no comando find, onde vê os caracteres {} (um por vez, uma invocação find será executada para cada diretório).

por 17.01.2018 / 00:59
2

Em tcsh , quando você cita uma substituição de comando, ela é dividida em uma base um por linha não vazia , que soa exatamente como você deseja aqui, então você pode fazer:

find -- "'cat list.txt'" -name '*.c'

Em shells do tipo POSIX, você precisa fazer algo como:

(set -o noglob; IFS='
'; find -- $(cat list.txt) -name '*.c')

para alcançar o mesmo.

Isso pressupõe que list.txt contenha pelo menos uma linha não vazia (caso contrário, dependendo da implementação de find , você receberá uma mensagem de erro ou procurará no diretório atual).

Isso também pressupõe que nenhuma das linhas começa com - ou são find predicados (a maioria dos find predicados começam com - ( -ok , -print , -type ...) , mas também há ! , ( , ) ...).

Isso também pressupõe que list.txt é pequeno o suficiente para caber no tamanho máximo de argumentos para um comando.

Outra alternativa é usar xargs .

<list.txt sed 's/"/"\""/g;s/.*/"&"/'|xargs tcsh -c 'find $argv:q -name "*.c"'

Em que sed cita cada linha em um formato entendido por xargs .

As mesmas limitações acima, exceto que ele deve contornar a limitação do número de argumentos executando tantos comandos find conforme necessário para evitá-los, e assume que o conteúdo de list.txt é texto válido na localidade atual. Algumas implementações de xargs também têm um limite bastante baixo no tamanho máximo de qualquer argumento que pode ser significativamente menor que o tamanho máximo de um caminho.

    
por 17.01.2018 / 22:53
1
$ (echo /tmp; echo /var/tmp) > file
$ find $(cat file) -prune
/tmp
/var/tmp
$ 

No entanto! Essa pode não ser uma idéia tão genial se houver, digamos, novas linhas nos nomes de diretório ou se a lista de nomes de arquivos for muito longa para o execve(2) máximo em argumentos ... com tcsh você deve usar backticks que o bourne shells estes dias desfavorecem a $(...) form

% find 'cat file' -prune
/tmp
/var/tmp
% 

embora isso novamente tenha todos os mesmos problemas que os sofridos sob as conchas de bourne.

    
por 17.01.2018 / 00:36
0
xargs -d \n bash -c 'echo find "$@" -name \*.c' bash <input_file

Remova o echo depois de verificar se ele faz o que você deseja.

    
por 17.01.2018 / 02:02
0

Outra maneira de fazer isso é com este código:

(echo directory1 ; echo directory2 ; echo directory3) > file
for d in $(cat file); do find $d -name '*.c'; done

Isso colocará os nomes dos diretórios em um arquivo executando o find usando os nomes dos diretórios e gerando os resultados. Os apóstrofos cuidarão de quaisquer espaços ou caracteres reservados nos nomes dos arquivos.

    
por 17.01.2018 / 22:32

Tags