Em bash
, você deve usar uma matriz para manter os caminhos como lidos pelo usuário. Em geral, é melhor manter strings separadas (nomes de caminho) separadas, em vez de concatená-las em uma única string que depois você precisa analisar corretamente para extrair as strings constituintes originais.
#!/bin/bash
echo 'Enter paths, one by one followed by Enter. End input with Ctrl+D' >&2
mypaths=()
while IFS= read -r -p 'Path: ' thepath; do
mypaths+=( -v "$thepath:/opt/$thepath" )
done
docker run "${mypaths[@]}" fedora
Aqui, o usuário é solicitado a inserir um caminho várias vezes até que pressione Ctrl + D . Os caminhos inseridos são salvos no array mypaths
, que é apresentado de tal forma que docker
pode usá-lo diretamente.
Quando não houver mais caminhos para ler, o comando docker
será chamado. O "${mypaths[@]}"
será expandido para os elementos citados individualmente da matriz mypaths
. Como as entradas da matriz são armazenadas da maneira como estão (com -v
como um elemento separado antes de cada string pathname:/opt/pathname
formatada especialmente), isso será interpretado corretamente pelo shell e por docker
. Os únicos caracteres que não serão tolerados nos nomes de caminho pelo código acima são as novas linhas, pois estão separando as linhas lidas por read
.
O script acima também aceitaria entrada redirecionada de um arquivo de texto contendo um único caminho por linha de entrada.
Observe que a cotação é importante. Sem as aspas duplas em torno das expansões de variáveis, você não seria capaz de usar caminhos contendo espaços em branco, e você também teria problemas com caminhos contendo caracteres especiais para o shell.
Relacionados:
Para não- bash
( sh
) shells:
#!/bin/sh
echo 'Enter paths, one by one followed by Enter. End input with Ctrl+D' >&2
set --
while printf 'Path: ' >&2 && IFS= read -r thepath; do
set -- "$@" -v "$thepath:/opt/$thepath"
done
docker run "$@" fedora
Aqui, usamos a lista de parâmetros posicionais em vez de uma matriz (já que matrizes diferentes de $@
não estão disponíveis em sh
em geral), mas o fluxo de trabalho é idêntico, além de imprimir o prompt explicitamente com printf
.
Implementando a sugestão no final do comentário de Stéphane Chazelas , para que o script tenha nomes de caminho em sua linha de comando, em vez de lê-los a partir de sua entrada padrão. Isso permite que o usuário passe nomes de caminhos arbitrários para o script, mesmo aqueles que read
não conseguem ler facilmente ou que um usuário não consegue digitar facilmente em um teclado.
Para bash
usando uma matriz:
#!/bin/bash
for pathname do
mypaths+=( -v "$pathname:/opt/$pathname" )
done
docker run "${mypaths[@]}" fedora
Para sh
usando a lista de parâmetros posicionais:
#!/bin/sh
for pathname do
shift
set -- "$@" -v "$pathname:/opt/$pathname"
done
docker run "$@" fedora
Ambos seriam executados como
./script.sh path1 path2 path3 ...