find e globbing (e curingas)

4

Eu tentei encontrar alguns arquivos ( *.e* ) que estão no mesmo diretório que outro arquivo ( md.tpr ). Eu precisava listá-los (para processamento adicional) usando o seguinte:

find . -name md.tpr -execdir ls *.e* \;

Eu tentei algumas variantes deste comando e algumas outras (incluindo a simples citação do comando passado para -execdir ou passando-o como sh -c 'ls *.e*' ou eval 'ls *.e*' para citar algumas). Parece que a globbing não está funcionando quando passada para -exec ou -execdir . O erro que recebo ao executar o comando acima é:

ls: *.e*: No such file or directory

Assim como uma verificação de sanidade, eu fiz -execdir pwd e imprime o que deveria, então parece que é um problema com globbing, já que os arquivos *.e* existem nos diretórios listados com este teste.

Agora, eu consegui resolver esse problema de uma maneira muito menos elegante, mas me surpreendeu porque globbing e curingas não funcionariam aqui. Alguma ideia? Ou eu estou completamente fora da pista?

Eu uso o bash 3.2.25 (antigo, mas não tenho direitos de administrador nesse sistema).

Além disso, curiosamente, se eu fizer

find ~ -name .bashrc -maxdepth 2 -execdir ls -d .b* \;

não funciona a menos que seja feito a partir de $HOME .

    
por Wojtek Rzepala 09.11.2012 / 22:26

2 respostas

7

O shell faz globbing, não find . Quando você digita um comando que inclui um glob sem aspas como .b* ou *.e* , o shell expandirá isso para você. Isso acontece antes que find o veja.

Você provavelmente tem arquivos como .bashrc , .bash_history etc. no diretório $HOME . Portanto, quando executado a partir de $HOME , seu comando se transformará em find ... -execdir ls -d .bashrc .bash_history ... \; . Quando executado a partir de outros locais, o .b* glob não corresponde a nada, portanto é transmitido. Isso ainda não funciona, pois é o shell que faz globbing, não find -exec . Se você quisesse que o glob fosse expandido para o -exec , você precisaria invocar um shell para fazer isso:

find ... -execdir sh -c 'echo globs: *' \;
    
por 09.11.2012 / 22:44
1

Both the find command and the shell are capable of file globbing.

Isso é incomum - a maioria dos comandos NÃO é capaz de globbing e depende inteiramente do shell para expandir globs. Mas encontrar é uma ferramenta de super mega poder do usuário mega que você pode muito facilmente se machucar com!

Exemplo: quando você faz o comando

   find /path -iname *.txt

A primeira coisa que acontece é que o shell tenta encontrar todos os arquivos que correspondem ao * .txt no diretório atual. Se encontrar algum, ele substitui os nomes de all pelos arquivos correspondentes para o glob e, em seguida, chama o comando find. O comando de busca nunca vê o glob se isso acontecer, o shell o expandiu para fora da existência.

Mas se não houver arquivos no diretório atual que correspondam ao glob, o shell encolhe seus ombros metafóricos e passa o glob inalterado para encontrar. Então, nesse ponto, o comando find (que entende globs, lembre-se) exibirá os nomes de todos os arquivos que encontrar em / path que correspondam ao glob.

Portanto, usar globs dessa forma significa que o find se comportará de maneira diferente, dependendo do conteúdo do diretório atual. Isso quase certamente não é o que você quer!

Para evitar que o shell adultere os globs antes que eles sejam encontrados, escape dos globs com o shell apropriado metacaractere citando. Geralmente isso significa apenas colocar seus globstrings entre aspas simples como essa

   find /path -iname '*.txt'

Remember, GLOBS ARE NOT REGEXES - the glob ".*" and the regex ".*" are very different and do not match the same strings!

    
por 09.03.2018 / 19:21

Tags