「*」を指定しないとキャッシュディレクトリが削除されるのはなぜですか?

「*」を指定しないとキャッシュディレクトリが削除されるのはなぜですか?

私はZSHをデフォルトのシェルとして使用し、その上にOhMyZshを使用します。場合によっては、一部のファイルを削除し、一部の権限/所有権をリセットする必要があるため、そのエイリアスを使用します。 PHP / Symfonyプロジェクトがあるとしましょう/home/parallels/Development/prj1。以下のスクリプトを使用すると実行できますがfixperms prj1...

  • スクリプトを一度実行して内容を削除すると、$CURRENT_PROJECT/$PROJECT_CACHE次のエラーが発生します。
fixperms:4: no matches found: /home/parallels/Development/prj1/framework/var/cache/*
  • *末尾を削除すると、不要なフォルダも$CURRENT_PROJECT/$PROJECT_CACHE/*削除されます。cache

  • ファイルはdev.log決して削除されません

私がここで何を見逃しているのでしょうか?

PROJECT=framework
PROJECT_VAR=$PROJECT/var
PROJECT_CACHE=$PROJECT_VAR/cache
PROJECT_LOG=var/log/dev.log

fixperms () {
  if [ -n "$1" ]; then
    CURRENT_PROJECT=$HOME/Development/"$1"

    cd $CURRENT_PROJECT && sudo rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/* && sudo rm -rf $CURRENT_PROJECT/$PROJECT_LOG && sudo chown -R "$(whoami)":root $CURRENT_PROJECT && sudo chmod -R 777 $CURRENT_PROJECT/$PROJECT_VAR
  else
    echo "Missing project param."
  fi
}

注:私はbash / shellスクリプトの専門家ではないので、どんな改善にも歓迎します。

答え1

すべてのジョブをリンクすると、&&そのいずれかが失敗した場合はジョブが中断され、その行以降のジョブは実行されません。これが意図的なものかどうかはわかりません。

たとえば、次のようになります。

echo A && false && echo B
echo A && true && echo B

したがって、dev.logアイテムキャッシュが失敗しても削除されないのはなぜですか?この行rm以降の内容は実行されません。rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*

zshデフォルトではオフになっているためnullglob失敗*します。


それでも。

ディレクトリが空であることを最初に確認してから、後で確認できますrm。最も簡単な方法は、単に削除して再作成することです。

setopt nullglobまたは後で選択してくださいunsetopt nullglob

その他の注意事項:

大文字変数を使用する理由があるかもしれませんが、可能であれば使用しないことをお勧めします。環境変数、組み込み関数などによって競合が発生する可能性があります。

もっと引用する必要があります。

私は$project_logそれがファイルであると仮定しているなら、-rそれは役に立ちません。

echo/printfエラーが発生しましたstderr

project=framework
project_var=$project/var
project_cache=$project_var/cache
project_log=var/log/dev.log

fixperms () {
    if [ -n "$1" ]; then
        current_project="$HOME/Development/$1"

        # Change to project directory. Exit if it fails.
        # The shell should give descriptive error.
        pushd "$current_project" || exit 1

        [ -e "./$project_cache/" ] && sudo rm -r "./$project_cache/"
        sudo mkdir "./$project_cache"

        [ -e "./$project_log" ] && sudo rm "./$project_log"

        sudo chown -R "$(whoami):root" .

        sudo chmod -R 777 "./$project_var"
        # Restore directory we started from
        popd
    else
        printf 'fixperms(): Missing argument: project\n' >&2
    fi
}

return 1代わりに、あなたが望むものはexit 1完全に機能を使用する方法によって異なります。

とにかく、存在するかどうかを確認すると-f削除します。rm

答え2

sudo rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*

コマンドの実行方法は次のとおりです(重要な部分のみを参照)。

  1. シェルは最後の引数の変数を拡張します。明らかになる/home/parallels/Development/prj1/framework/var/cache/*
  2. 最後のパラメータにはワイルドカードパターンが含まれているため、パターンがファイルと一致することを確認してください。アカウントにはリストされたファイルに対する権限がないため、パターンは/home/parallels/Development/prj1/framework/var/cacheどのファイルとも一致しません(シェルは「一致するファイルがないことを確認できます」と「一致するファイルがあるかどうかを確認できません」を区別できません) 。どのファイルとも一致しないワイルドカードパターンは維持されます。
  3. シェルはプログラムを実行するためにパラメータsudoを使用します。rm-rf/home/parallels/Development/prj1/framework/var/cache/*
  4. sudormパラメータを使用し-rfて実行します/home/parallels/Development/prj1/framework/var/cache/*
  5. rm指定されたファイルを削除します。つまり、*というディレクトリにファイルがある場合、/home/parallels/Development/prj1/framework/var/cacheそのファイルは削除されます(*ディレクトリの場合、その内容は繰り返し削除されます)。

ワイルドカード拡張(または削除するファイルを列挙するために使用されるすべての方法)を実行するには、ディレクトリに対する読み取り権限を持つシェルを準備する必要があります。これは、sudoを呼び出すシェルではなく、sudoで実行されているシェルでワイルドカード拡張が行われる必要があることを意味します。たとえば、

sudo sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"

サイズ変更時の注意事項を参考にしてください。sudo sh -c 'rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*'変数が内部シェルで定義されていないため動作しません(実行されますが、rm -rf //*試す必要はありません)。sudo sh -c "rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*"これは、関連する変数値にスペースなどの文字が含まれていない場合にのみ機能します。これは、ファイル名ではなくシェルコードの断片として解釈されるためです。

気づく上記のコマンドを実行しないことをお勧めします。、脆弱だからです。パスが期待したものと正確に一致しない場合、最終的にシステム内のすべてのエントリが削除され、コマンドがルートとして実行されるため、これは非常に悪い可能性があります。代わりに、必要な権限がある場合にのみコマンドを実行する必要があります。

sudo -u parallelsowner sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"

または

sudo -g parallelsgroup sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"

parallelsowner問題のディレクトリとそのサブディレクトリを所有しているユーザー、またはディレクトリparallelsgroupとすべてのサブディレクトリに対する書き込み権限を持つグループはどこにありますか?

関連情報