com zsh :
users=(User1 User2)
# or users=($(<userlist.txt))
# if userlist.txt contains a list of users as separate words
dirs=(Documents Pictures ...)
find ./$^users/$^dirs
Mesmo com fish :
set users User1 User2 ...
set dirs Documents Pictures
find ./$users/$dirs
Em fish ou zsh -o rcexpandparam , as matrizes se expandem de maneira expansiva. Em zsh , a sintaxe $^array ativa rcexpandparam para essa expansão de matriz única.
A referência a rc é um pouco enganadora aqui. Enquanto $array^string em rc / es (onde array é (1 2)) expandiria como {1,2}string (e essa é a razão pela qual zsh escolheu ^ para seu tipo de expansão rc em $^array ), isso não se aplica a unir matrizes. Em rc , $array1^$arrat2 (igual a $array1$array2 ) só funciona para matrizes do mesmo tamanho e une o elemento um por um ( (1 2)^(a b) se torna 1a 2b , não 1a 1b 2a 2b ).
Observe que esses não são globbing , User1/Documents será passado para find , independentemente de o arquivo existir ou não. Para passar a lista desses arquivos ou diretórios que realmente existem , em zsh , você poderia fazer
find ./$^users/$^dirs(N)
que passa adiciona o qualificador (N) glob a todo o elemento resultante da multiplicação da matriz, que tem dois efeitos:
- torna-os globs, o que significa que eles serão expandidos para arquivos correspondentes
- se o glob não corresponder a nenhum arquivo (eles podem corresponder apenas a 0 ou 1, pois não há nenhum caractere curinga), o glob resultante se expande para nada.
Alternativamente, você pode ir glob até o fim:
find (User1|User2)/(Documents|Pictures)
Ou com base no seu exemplo:
set -o extendedglob # best in ~/.zshrc
find ./^(#i)(Default|Public)/(Documents|Pictures)
Ou gere esse glob com base nos arrays com
find (${(j:|:)~${(b)users}})/${(j:|:)~${(b)dirs}}
Onde:
-
(b)cita os operadores de caractere curinga, se houver algum nos elementos da matriz -
(j:|:)une-se a eles com| -
~ativa a globulação na expansão
Eles trabalham com nomes de arquivos arbitrários (exceto aqueles que começam com - como uma limitação de find ).
Fazer isso com find sozinho seria muito complicado, especialmente se você quiser permitir nomes de arquivos arbitrários. Mas para seus relativamente domados como os Default , Public ...), você poderia tentar:
LC_ALL=C find . -name . -o -path './*/*' \( ! -path './*/*/*' \
! -name Documents ! -name Pictures -prune -o -print \) -o \
! -name Default ! -name Public -o -prune
(Esse tipo de coisa me dá dor de cabeça).
Usando a sintaxe find padrão, se você quiser uma correspondência sem distinção entre maiúsculas e minúsculas, use -name '[pP][uU][bB][lL][iI][cC]' ou, se estiver usando o GNU find (que pareça) ou compatível, use -iname Public .