zshシェルで実行されるシェルスクリプトでディレクトリを変更する方法

zshシェルで実行されるシェルスクリプトでディレクトリを変更する方法

シェルスクリプトを作成しています。 (シェルを使用するバージョンとオペレーティングシステムは次のとおりです。)このスクリプトは、ローカルのgitリポジトリ/ディレクトリで複数のタグを含むコマンドを実行します。スクリプトは、リポジトリタグ名に基づいて選択されたディレクトリのgrepファイルからいくつかの文字列を出力します。

zsh --version
zsh 5.9 (x86_64-apple-darwin22.0)
OS: System Version: macOS 13.6.3
+
using oh-my-zsh, https://ohmyz.sh/

このスクリプトはcdディレクトリ(コマンド)をgitローカルリポジトリに変更します。次に、配列のラベルを取得するプロセスを経ますMY_ARRAY=($(git tag))。次に、各ストレージタグに対してgit checkout $my_tag --quiet そのタグに対してアクションを実行します。その後、cdリポジトリのディレクトリ(directoryA)にあります。次に、pwd作業ディレクトリを確認するためにaを実行します/git-repository/directoryApwdこの時点の出力は予想通りです(/git-repository/directoryA)。これがあると、/git-repository/directoryAスクリプトはLIST_OF_SUBDIRECTORIES=($(ls -d */))のサブディレクトリ配列を取得します。directoryA出力は次のとおりですLIST_OF_SUBDIRECTORIES is cw-events/ cw-metric-alarm/ eventbridge-scheduler/ msk/ secrets-manager/ ses/ sns-topic/ sqs/ ssm-params/ xlate/。各サブディレクトリ(forループを使用)に対して、スクリプトは次のcdようにLIST_OF_SUBDIRECTORIES配列のサブディレクトリを指す必要があります。

if echo "$my_tag" | grep -q -E "$MY_SUBDIRECTORY"; then
          echo "MY_SUBDIRECTORY is $MY_SUBDIRECTORY"
          set -x
          cd $MY_SUBDIRECTORY 2>&1 | tee -a log_file.txt
          set +x
          echo "PWD Working Directory is $(pwd)"

if条件の出力がecho "MY_SUBDIRECTORY is $MY_SUBDIRECTORY"trueなのでスクリプトを入力MY_SUBDIRECTORY is cw-events/できるようにしたいのですが上記の内容が出力されています。スクリプトはで始まります。試行中にエラーが発生します。他の問題を発見しましたcdcw-events/echo "PWD Working Directory is $(pwd)"/git-repository/directoryA
#!/bin/zsh#!/bin/bash
https://blog.kubesimplify.com/how-to-change-directory-in-shell-scriptsまたは現在のディレクトリを変更するスクリプト(cd、pwd)しかし実際には、親シェルではなくサブシェルのディレクトリを変更したいと思います。の
中にスクリプト/git-repository/directoryAがにないのはなぜですか?出力例:私ができる簡単な例はスクリプト実行の出力です。cd/git-repository/directoryA/subdirectory-of-A

FIRST-SUB-Directory is /git-repository/directoryA
LIST_OF_SUBDIRECTORIES is cw-events/ secrets-manager/ sqs/ ssm-params/
MY_SUBDIRECTORY is cw-events/
+/path/to/script/script.sh:44> cd cw-events/
+/path/to/script/script.sh:44> tee -a log_file.txt
+/path/to/script/script.sh:45> set +x
PWD Working Directory is /git-repository/directoryA


ありがとうございます。

ベストアンサー1

この行は明らかに間違っています。

cd $MY_SUBDIRECTORY 2>&1 | tee -a log_file.txt

パイプの左側はサブシェルで実行されます。これは、内部変更(変数、現在のディレクトリなど)がプライマリシェルに影響を与えないことを意味します。バラよりCDをレコーダーにリダイレクトできないロギングの追加の説明とアドバイス。cd -// cd -2...cd +2ディレクトリスタックを検索するときを除いてcd失敗しない限り、出力はエクスポートされないため、出力を記録することはとにかく意味がありません。

cd $MY_SUBDIRECTORY行を(またはより良い場合)に変更すると、cd -- $MY_SUBDIRECTORY少なくとも公開したスクリプト部分に対してディレクトリ変更が機能します。スクリプトの後半でまだ元のディレクトリにある場合は、サブシェルを作成するために別の作業を行っている可能性があります(まだ公開していないコードの一部)。


それ以外には目立って間違ったことはありませんが、いくつかは必要以上に複雑です。間違いのリスクを減らすために、より簡単な方法でタスクを実行することをお勧めします。

  • あなたは使うecho そして set -x そして | tee …文書化する。一つで十分です。set -xほとんどの場合は大丈夫です。パイピングはteeスクリプトの動作(サブシェルの作成、ファイル記述子の変更、エラーの非表示)に影響を与えるため、難しいです。

  • echo "$my_tag" | grep -q -E "$MY_SUBDIRECTORY"値に拡張正規表現演算子(commonタグやgitタグなど)が含まれていないとし、値に部分文字列値がmy_tag含まれていることを確認してください。簡単に確認する方法があります。MY_SUBDIRECTORYMY_SUBDIRECTORY.+

    if [[ $my_tag = *"$MY_SUBDIRECTORY"* ]]; then …
    
  • LIST_OF_SUBDIRECTORIES=($(ls -d */))LIST_OF_SUBDIRECTORIES=( *(-/) )zsh を使用して作成できます。/ グローバル予選、ファイルタイプ、およびその他の特性でグローブをフィルタリングできます。ここで、-so型チェックと組み合わせた操作は、シンボリックリンクの確認後に行われます*/。各要素の末尾にスラッシュは追加されません。…=( *(-/M) )スラッシュが本当に必要な場合や使用可能なディレクトリのみをリストする特別な場合には機能します…=( */ )が、実際にはスラッシュは必要ないかもしれません。Nサブディレクトリがない場合に致命的なエラーの代わりに空のリストを取得するには、glob修飾子を追加してください。

    LIST_OF_SUBDIRECTORIES=( *(N-/) )
    

echo "$my_tag"厳密に言えば、as出力のすべての行はgrep一度に1行ずつ一致し、改行文字にも拡張echoされます\n(幸いにも、gitタグにバックスラッシュが含まれていないことを保証する必要があります)。

おすすめ記事