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
.