Como faço para “encontrar” apenas arquivos de correspondência em subdiretórios específicos

1

Estou usando o bash para o Mac OS X 10.6.8.

Usando o comando find , gostaria de procurar arquivos que correspondam a *.XML . No entanto, gostaria de corresponder apenas esses arquivos no subdiretório 16xxxx e não em 16yyyy de algum diretório base.

basedir/16xxxx/EX1.XML
basedir/16xxxx/EX2.XML
basedir/16yyyy/EX3.XML
basedir/16yyyy/EX4.XML

Os resultados que estou procurando seriam EX1.XML e EX2.XML (nome completo do caminho excluído para maior clareza).

Isso está no contexto de um script BASH que tornaria conveniente se eu pudesse inserir 16xxxx/*.XML como a expressão a ser transmitida para -name no comando find :

find basedir -name '16xxxx/*.XML'

No entanto, isso não retorna nenhuma correspondência porque o shell não corresponde ao caractere / . Existe algum argumento para passar para find ou uma maneira de escapar da expressão 16xxxx/\*.XML que retornará os resultados que eu preciso?

    
por stever 22.02.2012 / 01:41

1 resposta

4

A opção -name nunca funcionará após o primeiro / . Como sempre, as páginas man são seus amigos:

 -path pattern
         True if the pathname being examined matches pattern.  Special shell pattern matching characters
         (''['', '']'', ''*'', and ''?'') may be used as part of pattern.  These characters may be
         matched explicitly by escaping them with a backslash (''\'').  Slashes (''/'') are treated as
         normal characters and do not have to be matched explicitly.

Eu geralmente prefiro a compatibilidade com o GNU find e, portanto, uso a opção -wholename . Note que estes também existem no modo sem distinção entre maiúsculas e minúsculas: -iwholename e -ipath .

Então, no seu caso, você faria (lembre-se que wholename corresponde ao caminho todo , então você deve adicionar o curinga * no começo):

karolos$ find basedir -type f
basedir/16xxxx/EX1.XML
basedir/16xxxx/EX2.XML
basedir/16yyyy/EX3.XML
basedir/16yyyy/EX4.XML
karolos$ find basedir -wholename "*16xxxx/*.XML"
basedir/16xxxx/EX1.XML
basedir/16xxxx/EX2.XML

Outra maneira de conseguir o que você deseja é usar o find em combinação com grep (note que eu tive que alterar a expressão regular, adicionando um . (para qualquer caracter) antes do curinga * ):

karolos$ find basedir | grep '16xxxx/.*.XML'
basedir/16xxxx/EX1.XML
basedir/16xxxx/EX2.XML

Por fim, dependendo das suas necessidades, existe até a possibilidade de você não precisar usar find (se você não precisar da flexibilidade extra). Você pode então usar bash expansão de nome de arquivo da seguinte forma:

karolos$ echo basename/*16x*/*XML
basename/16xxxx/EX1.XML basename/16xxxx/EX2.XML
    
por 22.02.2012 / 02:32

Tags