シェルの動的変数

シェルの動的変数

ユーザーから入力(ソースパス)を受け取り、Dockerコンテナ内のボリュームに接続する次のスクリプトがあります。

echo -n "Enter the source path: "

read path

docker run -v $path:/opt/$path/ fedora

問題は、ユーザーが複数のソースパスを提供してDockerコンテナに接続できるようにループを作成したいということです。

例えば

docker run -v $path1:/opt/$path1 -v $path2:/opt/$path2

そして、$pathこれらの変数の数はユーザー入力によって異なります。

答え1

では、bashユーザーが読み取ったパスを保持するために配列を使用する必要があります。通常、個々の文字列(パス名)を後で元の構成文字列を抽出するために正しく解析する必要がある単一の文字列にリンクするよりも、分離する方が良いです。

#!/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

ここで、ユーザーはを押すまでパスを数回入力する必要がありますCtrl+D。入力パスはmypaths配列に保存され、配列のレイアウトをdocker直接使用できます。

これ以上読み取るパスがない場合、dockerこのコマンドが呼び出されます。"${mypaths[@]}"配列で個別に参照される要素に展開されますmypaths。配列のエントリはそのまま(-v特別にフォーマットされた各文字列の前に別々の要素としてpathname:/opt/pathname)格納されるため、dockerシェルと上記のコードがパス名で受け入れられない唯一の文字は、読み取る行を区別するためですread

上記のスクリプトは、入力行ごとに単一のパスを含むテキストファイルのリダイレクトされた入力も許可します。

引用が重要であることに注意してください。変数拡張の周りに二重引用符がない場合、スペースを含むパスは使用できず、シェル特殊文字を含むパスに問題が発生する可能性があります。

関連:


bash()シェルではない場合sh

#!/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

ここでは配列の代わりに位置引数のリストを使用しますが(それ以上の配列は通常使用$@できないためsh)、明示的な印刷ヒントを使用することを除いて、ワークフローは同じですprintf


実装するStéphane Chazelasのコメントの最後にアドバイス、スクリプトが標準入力からパス名を読み取るのではなく、コマンドラインからパス名を取得するようにします。これにより、readユーザーは読みやすく、キーボードで簡単に入力できないパスでも、任意のパス名をスクリプトに渡すことができます。

配列を使用するにはbash

#!/bin/bash

for pathname do
    mypaths+=( -v "$pathname:/opt/$pathname" )
done

docker run "${mypaths[@]}" fedora

sh位置引数リストを使用する場合:

#!/bin/sh

for pathname do
    shift
    set -- "$@" -v "$pathname:/opt/$pathname"
done

docker run "$@" fedora

どちらもこのように実行されます

./script.sh path1 path2 path3 ...

答え2

これを試してみてください。ディレクトリ名にスペースを含めることはできません。

#!/bin/bash

echo -n "Enter the Directories, space separated : "
read dirs

docker run $( set -- $dirs; for path; do echo -v $path:/opt/$path/; done ) fedora

このように入力するfoo barと実行されます。

docker run -v foo:/opt/foo/ -v bar:/opt/bar/ fedora

答え3

#!/bin/bash

echo -n "Enter the Path : "
read path
echo -n "docker run "
echo "${path}" | tr " " "\n" | while read value
do
    echo -n "-v ${value}:/opt/${value} "
done

関連情報