私は次のコードを使用します。このスクリプト私はこれを使ってWordPressサイトを更新します。
#!/bin/bash
drt="/var/www/html"
for dir in ${drt}/*/; do
if pushd "$dir"; then
wp plugin update --all --allow-root
wp core update --allow-root
wp language core update --allow-root
wp theme update --all --allow-root
popd
fi
done
すべてのWordPressインスタンスを一度に更新する方法を探している間、このコードで使用されている特定のパターンについて学びましたpushd
。popd
このコードにセグメントが含まれている理由は不明ですif-fi
。
私の質問
基本的に、同じパターンを持つがif-fi
セグメントがないように構文を何とか変更できますか?
たとえば、次のように変更します。
if pushd "$dir";
popd
commands
fi
私は次の疑似コードを持っています:
pushd "$dir";
commands
popd
私はこれをなぜ尋ねますか?
if-fi
宣言(擬似コード)なしで、コンピュータに次のように話す方法を想像できます。
for dir in ${drt}/*; do pushd "$drt"; then
commands
popd
ノート
答えに他のアプローチを含めることもできます(つまり、まったく含まれていません)
pushd
。popd
関連質問。
答え1
また@Olorinによる投稿ここには少し誤解がある可能性があると思います。まずfor y in ${x}/*; do pushd "$y"; then
、結果は
bash:予期しないトークン「then」の近くに構文エラーがあります。
第二に、インデントが誤解を招く可能性があります。実際に起こったことについて。元のコードの正しい形式のバージョン:
for y in ${x}/*/
do
if pushd "$y"
then
command1
command2
popd
fi
done
つまり、みんな command1
、初期成功が発生した場合command2
にのみ実行されます。代わりに書くならpopd
pushd
for y in ${x}/*/
do
pushd "$y"
command1
command2
popd
done
そして、errexit
ガードがなければ、失敗pushd
や失敗はpopd
スクリプトの残りの部分に影響を与えません。これにより、間違ったディレクトリが実行され、command1
入力されて別のディレクトリに戻る可能性があります。command2
このコードとは何の関係もありません。これは悲惨な結果につながる可能性があります。
最後に言いたいことはpushd
+コマンド+はpopd
アンチパターンです言語にさらに多くのコンテキスト(したがって認知的オーバーヘッドとリスク)を追加し、複雑なコンテキストがすでに大きな問題であるためです。この問題を解決する最も一般的な方法は、次のようにコマンドにパス(絶対パスを推奨)を渡すことです。
for y in "$x"/*/
do
command1 "$y"
command2 "$y"
done
答え2
失敗するとpushd
どうなりますか?これらのディレクトリでコマンドを実行する場合は、pushd
コマンドを続行する前に成功するかどうかを明確に確認する必要があります。
答え3
ifを使用することは、ディレクトリ変更の失敗に対する合理的な保護です。
ディレクトリが実行可能でない場合(x権限なし)、このコードは親ディレクトリでコマンドを実行します。
#!/bin/bash
drt="/var/www/html"
for dir in "${drt}"/*/
do pushd "$dir"
pwd
popd
done
いくつかのディレクトリを構築し、所有者と権限を変更します。
$ mkdir -p /var/www/html/{one,two}
$ sudo chown user:user /var/www/html/{one,two}
$ sudo chmod o-x /var/www/html/two
$ ./script
/var/www/html/one ~/temp
/var/www/html/one
~/temp
./script: line 5: pushd: ./var/www/html/two/: Permission denied
~/temp
./script: line 7: popd: directory stack empty
Pushdコマンドはエラーを生成しますが、pwdコマンドは〜/ tempディレクトリから実行されます(エラー後に印刷される〜/ temp値に注意してください)。これは明らかに間違ったことをする危険があります。このスクリプトと比較してください。
#!/bin/bash
drt="./var/www/html"
for dir in "${drt}"/*/
do if pushd "$dir" 2>/dev/null
then
pwd
popd
fi
done
新しいスクリプトが実行されました。
$ ./script
/var/www/html/one ~/temp
/var/www/html/one
~/temp
または、より良い方法は次のとおりです。
#!/bin/bash
drt="./var/www/html"
for dir in "${drt}"/*/
do if pushd "$dir" 2>/dev/null
then
pwd
popd
else
echo "Failed to change to dir=$dir" >&2
exit 7
fi
done
実行すると、次のように印刷されます。
$ ./script
/var/www/html/one ~/temp
/var/www/html/one
~/temp
Failed to change to dir=/var/www/html/two/
答え4
gnu-findを使用すると、次のことができます。
find ${drt} -maxdepth 1 -type d -execdir command1 ";" -execdir command2 ";"
すべてのfind実装に-execdirオプションがあるわけではありません。