Não é a expansão de y
, mas o valor atribuído a y
é o problema.
Você tem isso
y=$($x/*(o+rand[1]))
O valor atribuído é o resultado da substituição do comando ( $(…)
). A única “palavra” no comando substituído é a expressão glob. Isso significa que ele tentará executar o arquivo selecionado como um comando (o que provavelmente causará um erro e não produzirá nenhuma saída útil).
Para fazê-lo funcionar (embora com uma mudança na semântica), você pode alterar sua atribuição de substituição de comando em uma atribuição de matriz (por exemplo, remover o $
após o =
):
y=($x/*(o+rand[1]))
Se você quiser manter a substituição do comando, você precisa fazer com que ele exiba o nome do caminho selecionado em vez de tentar executá-lo como um comando:
y=$(print -- $x/*(o+rand[1]))
Mas há um problema oculto aqui. Cada glob será avaliado em um subshell separado, portanto, cada diretório usará a mesma sequência de números aleatórios para classificar suas entradas. Você pode observar isso se usar set -x
e observar a sequência de valores atribuídos a REPLY para cada diretório. Isso significa que os arquivos não serão selecionados independentemente entre diretórios.
Aqui estão algumas abordagens alternativas que você pode usar para atribuir uma expansão glob a um parâmetro (elas mantêm a avaliação $RANDOM
no mesmo shell, portanto as seleções serão (mais) independentes):
for y in $x/*(o+rand[1]); do print -- ${y:r}; done
set -- $x/*(o+rand[1]); print -l -- ${@:r}
Se você deseja manipular diretórios vazios, provavelmente deve adicionar o qualificador N
glob (age como se NULL_GLOB estivesse definido). Isso também ajudará a manipular diretórios não correspondentes ao glob externo (embora você possa usar o qualificador /
glob para limitar esse apenas aos diretórios).
rand() REPLY=$RANDOM
for x in *(/); do y=($x/*(No+rand[1])); print -l -- ${y:r}; done