Muitas vezes preciso encontrar um arquivo, mas não tenho certeza de qual é o nome, algo assim:
$ find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
Isso é um pouco tedioso. Gostaria de criar um alias que seja mais fácil de usar, assim:
$ findany foo bar blah
Aqui está minha tentativa:
findany() {
args=("-iname" "'*$1*'")
shift
while [ $# -gt 0 ]; do
args+=("-o" "-iname" "'*$1*'")
shift
done
find ${args[@]}
}
O problema é que nunca produz nenhum resultado, mesmo que os arquivos estejam ali:
$ ls
bar.txt blah.txt foo.txt
$ findany foo bar blah
# nothing
Se eu adicionar echo
na frente do comando, parece correto:
$ findany foo bar blah
find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
E se eu copiar a saída acima e executá-la, funcionará bem:
$ find -iname '*foo*' -o -iname '*bar*' -o -iname '*blah*'
./bar.txt
./foo.txt
./blah.txt
Acho que tem a ver com divisão de argumentos ou aspas, mas não sei como depurá-lo.
Normalmente uso zsh, mas verifiquei o mesmo comportamento no bash.
Você estava muito perto! Mas, por algum motivo, você incluiu aspas simples nos próprios nomes dos arquivos, para que nunca correspondessem.
Além disso, você deve fazer uma cotação
"${args[@]}"
para que funcione corretamente. Caso contrário, estará sujeito à divisão de palavras e quaisquer globs se expandirão no shell antes defind
serem vistos.Em vez disso, tente isto (especificamente para
bash
):Com zsh, você poderia simplesmente usar:
Para construir esse padrão a partir de uma matriz, você pode usar o
j[|]
sinalizador de expansão de parâmetro para unir os elementos da matriz combinado|
com o~
sinalizador de expansão de parâmetro para que|
seja tratado como um operador de padrão glob ou com o~
operador de expansão de parâmetro para que qualquer caracteres curinga na string unida (mesmo aqueles encontrados em elementos da matriz) são tratados como padrões.Ou:
Por exemplo,
findany1 '??'
encontraria os arquivos cujo nome contém??
enquantofindany2
encontraria os arquivos cujo nome contém pelo menos 2 caracteres. Você precisariafindany2 '\?\?'
encontrarfindany2 '[?][?]'
os arquivos cujo nome??
contémfindany2
.Para fazer a mesma distinção com
find
, seria:Onde escapamos dos curingas reconhecidos por
find
(?
,*
,[...]
e\
) com\
(o único operador de aspas suportado porfind
/fnmatch()
).essa é uma maneira de fazer isso, mas, francamente, em termos de resultados é semelhante a
(mas faz isso sem a ajuda de
find
).Podemos construir rapidamente um script de shell a partir disso.
Se você quiser tê-lo como uma função, basta colocar
pattern=…
todone
em uma declaração de função.