web-dev-qa-db-ja.com

ファイルグロブを一緒にチェーンすることは可能ですか?

保存私は_{1..40}0.txt_という名前の一連のファイルを持っています(したがって_10.txt_から_400.txt_まで10):

_➜ ls
10.txt  60.txt   110.txt  160.txt  210.txt  260.txt  310.txt  360.txt
20.txt  70.txt   120.txt  170.txt  220.txt  270.txt  320.txt  370.txt
30.txt  80.txt   130.txt  180.txt  230.txt  280.txt  330.txt  380.txt
40.txt  90.txt   140.txt  190.txt  240.txt  290.txt  340.txt  390.txt
50.txt  100.txt  150.txt  200.txt  250.txt  300.txt  350.txt  400.txt
_

100〜300であるが、100で割り切れないすべてのファイルを削除したい。 _{1..9}0.txt_、_100.txt_、_200.txt_、_3{1..9}0.txt_を残す:

_rm 110.txt  130.txt  150.txt  170.txt  190.txt  220.txt  240.txt  260.txt  280.txt
   120.txt  140.txt  160.txt  180.txt  210.txt  230.txt  250.txt  270.txt  290.txt
_

Zshでは、_<100-300>.txt_を使用して100から300のファイルをグロブでき、^(*00).txtを使用して100で割り切れるファイルをグロブできます(extendedglobオプションを設定)。

ファイルグロブパターンを次々にチェーンすることは可能ですか?したがって、100-300ファイルをグロブし、次に_00_?

単一のグロブでこれを行う方法は<100-300>.txt~(*00).txtであることに注意してください。ここで、_~_は除外を提供します( zshのドキュメント を参照)。編集:グロブゴルフをすることで、_<10-30>0*~*00*_まで下げることができます。

3
James Wright

グロブを次々とチェーンする場合は、_grep pattern | grep another-pattern_または_grep pattern | grep -v excluded-pattern_の同等のものを意味します。つまり、ファイルを一致させ、後で、2回目の反復でそのリストをさらに絞り込むには、_${array:#exclude-pattern}_および${(M)array:#only-pattern}演算子を使用します。

_list=(*(N))                      # all non-hidden files
list=(${(M)list:#<100-300>.txt}) # only retain the ones matching that pattern
list=(${list:#*00.txt})          # remove the ones matching that other pattern
_

それ以外の場合、あなたの場合、(とにかく私にとって)最も明白なアプローチは、その_~_ AND-NOT(except)演算子を使用することです(extendedglobが必要)。次のように行うこともできます:

_list=((<100-300>~*00).txt(N))
_

"Chaining"グロブ演算子は次のとおりです:

  • または:_|_(EREと同様ですが、_(...)_はパイプ演算子でもあるため、_|_内のみ):_(patternA|patternB)_
  • AND-NOT:_~_(with extendedglob):_patternA~patternB_
  • NOT:_^_(extendedglob付き)または!(pattern)kshglobあり、histexpandなし、または最初の文字として別​​の文字を使用_$HISTCHARS_)
  • AND:_~^_(つまり、AND-NOT-NOTとextendedglob)、または!(!(patternA)|!(patternB))kshglob

@ Kusalanandaが示しています のように、eグロブ修飾子を使用して、任意のシェルコードの実行に基づいてグロブ選択をさらに絞り込むこともできます。

次のようなこともできます:

_list=(*(Ne['[[ $REPLY = <100-300>.txt ]] && [[ $REPLY != *00.txt ]]']))
_
1
$ touch {10..400..10}.txt
$ print -rC1 -- <100-300>.txt(e['(( $REPLY:r % 100 != 0 ))'])
110.txt
120.txt
130.txt
140.txt
150.txt
160.txt
170.txt
180.txt
190.txt
210.txt
220.txt
230.txt
240.txt
250.txt
260.txt
270.txt
280.txt
290.txt

上記のtouchはファイルを作成します。

次の行の<100-300>.txtビットは、100から300までの数字で始まるファイルを選択します。

グロブ修飾子(e['(( $REPLY:r % 100 != 0 ))'])は、「ルート」(拡張子なしの名前、:rを介して持っていた)が100で割り切れないファイル名を選択します。


もちろん、すべてをglob修飾子を介して行うこともできます。

*.txt(e['(( r=$REPLY:r, r >= 100 && r <= 300 && r % 100 != 0 ))'])
2
Kusalananda