web-dev-qa-db-ja.com

変数に格納されているスペース区切りの引数をコマンドに渡します

私はインターネットからかなりきちんとしたバックアップスクリプトをハイジャックしましたが、どこかでこのようなことが起こっています

DIRS="/home/ /var/www/html /etc"

tar -czf /backup/file.tar.gz "${DIRS}"

私のマシンではたまたまうまくいきますが、私のサーバーでは、それが単一のパスであると考えて、存在しないことを教えてくれます。

/bin/tar: /home/ /var/www/html /etc: Cannot stat: No such file or directory 
/bin/tar: Exiting with failure status due to previous errors

ローカルのtarバージョンは1.29で、サーバーは1.28です。

その変数とは別にtarにディレクトリを提供する適切な方法は何ですか?

2
php_nub_qq

これがbashスクリプト(またはshのほとんどのバージョン)である限り、変数ではなく配列を使用して引数を渡す必要があります。

DIRS=('/home/' '/var/www/html' '/etc')

tar -czf /backup/file.tar.gz "${DIRS[@]}"

これは、必要に応じて次のように書くことができます(通常、配列が大きくなると読みやすくなります)。

DIRS=(
    '/home/' 
    '/var/www/html' 
    '/etc'
)

配列をサポートしないシェルでは、Word分割を許可するために変数の引用符を外す必要があります(回避できる場合は推奨されません):

DIRS="/home/ /var/www/html /etc"

tar -czf /backup/file.tar.gz ${DIRS}

これらの引数を渡すために変数を引用するとき、それは本質的に同じです:

tar -czf /backup/file.tar.gz "/home/ /var/www/html /etc"

ただし、引用符で囲まれた配列にそれらを渡すと、次のようになります。

tar -czf /backup/file.tar.gz "/home/" "/var/www/html" "/etc"

引用符で囲まれていない配列または変数を介してそれらを渡すと、次のような処理が実行されます。

tar -czf /backup/file.tar.gz /home/ /var/www/html /etc

この例では、これは問題にはならないはずですが、望ましくない、または潜在的に有害である可能性のある追加の単語分割やその他のタイプの拡張にさらされています。

4
jesse_b

Jesse_bに同意します。可能であれば配列を使用してください。

dirs="/home/ /var/www/html /etc"
dirs=($dirs)
tar -czf /backup/file.tar.gz "${dirs[@]}"

私は、bashのすべてのcaps変数を回避することをお勧めします。慣例により、環境変数と内部シェル変数は大文字になります。重要なものを上書きしないように、他のすべての変数名は小文字のままにしておくことをお勧めします。

0
Jon Red