Por que os argumentos entre chaves não se expandem neste caso?

5

Por exemplo, eu quero colocar alguns nomes de arquivos dentro de chaves para expansão assim:

$ ls
blue_texture  blue_waves  green_light
$ ls -m | tr -d ' \n'
blue_texture,blue_waves,green_light 
$ echo foo/bar/{'ls -m | tr -d ' \n''}
foo/bar/{blue_texture,blue_waves,green_light}

Minha pergunta por que não apoia o trabalho de expansão aqui? Eu esperava que funcionasse da seguinte forma:

$ echo foo/bar/{blue_texture,blue_waves,green_light}
foo/bar/blue_texture foo/bar/blue_waves foo/bar/green_light
    
por Maxim 15.11.2012 / 12:10

2 respostas

7

A razão pela qual isso não funciona é porque bash executa a substituição de chaves antes do comando (o Manual de Referência do Bash tem algumas informações sobre isso). A substituição não é executada até que a expansão da chave já tenha ocorrido.

A única maneira de fazer isso é usando eval , mas não faça isso neste caso, pois você permitirá a execução arbitrária de comandos.

Em vez disso, você precisa procurar outro método. Isso deve produzir a saída que você procura:

for file in *; do
    printf '%s ' "foo/bar/$file"
done; echo
    
por 15.11.2012 / 12:12
2

Com zsh:

files=(*)
echo foo/bar/$^l

( ${^array} ativa a expansão de estilo de expansão de chave para o array).

Ou:

echo ./*(:s:.:foo/bar:)

Aplica uma substituição de estilo de expansão de histórico à expansão de nome de arquivo.

Com qualquer casca

printf 'foo/bar/%s\n' *

Ou:

set -- *
for i do
  set -- "$@" "foo/bar/$i"
  shift
done
echo "$@"

(note que echo na maioria dos shells realiza algumas transformações nos argumentos que recebe, por isso é melhor evitar entradas arbitrárias).

    
por 15.11.2012 / 12:41