埋め込み配列と埋め込みグローブを除く配列から作成されたファイル配列を取得します。

埋め込み配列と埋め込みグローブを除く配列から作成されたファイル配列を取得します。

私は次のことをしたいと思います:

  • プロセスに含める基本ファイルのコレクションを指定するグローバル配列を定義します。
  • このプロセスから除外するファイルを指定するグローバル配列を定義します。このglob配列で指定されたファイルが上記のセットにないかどうかは私にとって重要ではありません。
  • 配列の構築文書(globではない)、含むglob配列に指定されたすべてのファイルを取得し、除外されたglob配列に属するすべてのファイルを削除します。

私はこれで苦労しています。進捗状況と私が試した作業のいくつかの明確な例を示すために、次の作業を試しました。

# List all files to potentially include in the process
files_to_include=(
    'utils/*.txt'
)

# List any files here that should be excluded from the above list
files_to_exclude=(
    '*dont-use.txt'
    'utils/README.md'
)

# Empty array of files
files=()

for file in ${files_to_exclude[@]}; do
    temp=find $files_to_include -type f \( -name '*.txt' -and -not -name $file \)
    files+=$temp
done

# I want this to be the total collection of files that I care about
echo ${files[@]}

明らかに、このforループロジックは機能しませんが、少なくとも起動するようになりましたが、まだこれを実行する適切な方法を見つけるのが困難です。 (出力を割り当てようとすると、奇妙な権限拒否メッセージが表示されます。なぜそのようなことが起こるのかわかりませんfindtemp

find私が理解したのはgrep。これにはいくつかの方法がありますが、スクリプトで「魔法」をできるだけ少なく使用したいと思います。したがって、スクリプトを効率的かつ理解しやすくするのに役立ちます。

私が知っている限り、include配列のすべてのglobを拡張し、除外配列のすべてのglobを拡張してから、include配列から除外項目を減算するプロシージャが必要です。しかし、これは非常に高いレベルであり、それを実装するのは私にとって難しいことです。

ありがとうございます!

答え1

files_to_includeあなたはglobになりたいと思うかもしれませんが、単なるfiles_to_excludeパターンでなければなりません。それ以外の場合、globは*dont-use.txt機能しません。生産するファイル名の生成またはパス名拡張他の名前のワイルドカードです) したがって、utils/whatev-dont-use.txtファイルを除外せず、utils/*.txt単にパターンであっても一致しますutils/.git/foo/bar/.txt

zsh一つある~ パターンとして除外glob演算子を使用すると、次のことができます。

set -o extendedglob
globs_to_include=(
  'utils/*.txt'
)

patterns_to_exclude=(
  '*dont-use.txt'
  'utils/README.md'
)

typeset -U files=(
  $~^globs_to_include~(${(j[|])~patterns_to_exclude})(ND.)
)

または、必要でない場合は、ポストextendedglobフィルタリングにパラメータ拡張演算子を使用します。patterns_to_exclude${array:#pattern}

typeset -U files=( $~^globs_to_include(N.) )
files=( ${files:#(${(j[|])~patterns_to_exclude})} )

両方の配列がパターンで、現在の作業ディレクトリ内またはその下にあるすべての一般ファイルのパスと一致させる場合は、次のようになります。

() {
  files=( ${${(M)@:#(${(j[|])~patterns_to_include})}:#(${(j[|])~patterns_to_exclude})} )
} **/*(ND.)

または段階的に明確に説明してください。

pattern_to_include="(${(j[|])patterns_to_include})"
pattern_to_exclude="(${(j[|])patterns_to_exclude})"
files=( **/*(ND.) )
files=( ${(M)files:#$~pattern_to_include} )
files=( ${files:#$~pattern_to_exclude} )

どちらもグローバルでなければならない場合は、次のようになります。

typeset -U files_to_include=(
  utils/*.txt(ND.)
)
typeset -U files_to_exclude=(
  *don-use.txt(ND.)
  utils/README.md(ND.)
)
files=( ${files_to_include:|files_to_exclude} )

${A:|B}配列減算演算子を使用してください。

これらのzsh関連構文のいくつかについての説明:

  • array=( elements ):bashが最終的に2.0で配列サポートを追加した後、一部のシェルによってコピーされた配列宣言。 Kornシェルに似ていますset -A array -- elements
  • **/:再帰ワイルドカードに使用されるすべてのレベルのディレクトリ。
  • extendedglob~オプション:オペレーターが必要
  • typeset -U array:配列要素を一意にします。
  • $~var:コンテンツが$varスキーマとして処理されるようにします。
  • $^array/more:拡張機能をelement1/more element2/morecshスタイルでクールに{element1,element2}/moreします。
  • ${(...)param}これはパラメータ拡張フラグです。配列の要素を追加するj[|]ために使用されます。j|
  • (ND.):これはglob修飾子です。ファイルの種類を制限するために、対応するNglob、Ddot globdotに対してnullglobを有効にします。.定期的な
  • ${array:#pattern}パターンに一致する要素をフィルタリングします。(M)ロゴと、フィルタリング
  • () { body; } args:匿名関数はいくつかの引数を渡しました(別名名前付き関数と同様に、$@aka$argv$1...で利用可能$2)。

答え2

引用があなたに不利ではなくより有利に作用するようにしなさい。グローブを引用しないで、シェルがグローブを拡張するようにしてください。変数がワイルドカードとして扱われないようにするには、変数の周りに二重引用符を使用してください。@二重引用符を含む配列特殊記号を入力することを忘れないでください。

includes=( utils/*.txt )
excludes=( *dont-use.txt utils/README.md )

# Convert array to hash so we can easily index it
declare -A excludes_hash
for i in "${excludes[@]}"
do
    excludes_hash["$i"]=1
done

# Build list of files
files=()
for i in "${includes[@]}"
do
    [ -z "${excludes_hash[$i]}" ] && files+=("$i")
done

# Total collection of files that I care about
printf "%s\n" "${files[@]}"

関連情報