の続き。前の記事で、ディレクトリー「dir」以外の全てのファイル及びディレクトリーを指定する方法に「^dir]* と書いた。これは誤りだった。訂正記事を書く。
除外用の glob pattern
除外したいファイルがある場合、zsh では「*~除外したファイル名」という書式を使う。前エントリーからのお題をそのまま使うと、こうなる:
$ ls a.html b.html c.html img/ $ mkdir dir $ mv *~dir dir $ ls dir/
dir ディレクトリー以外のファイル及びディレクトリーを全て dir ディレクトリーに mv する。
利用には .zshrc に setopt EXTENDED_GLOB
を入れておく必要がある。
何故、[^dir]* は誤りか
まず、ぼくがこの記事を書いた時、参照記事に既にこのやり方が誤りである、と記述があったことを強調しておきたい。ぼくは、「何が誤っているのか分からなくて」、このやり方を記事にしてしまった。全てぼくの不徳とする所。
さて、何故「^dir]* が誤りか。
このやり方は正規表現を使っている。[文字] は、括弧内に含まれる文字列のうち一文字を表す。つまり、[dir] ならば d か i か r という文字を表す。[^文字] はその否定。括弧内に含まれる文字以外を表す。従って、[^dir] ならば「d か i か r 以外の文字」を表す。ここに表てのファイル名を表す glob 表現「*」を続けると、[^dir]* の意味はこうなる。
先頭文字が d もしくは i もしくは r で始まらないファイル/ディレクトリーの全て
サンプル・コードでは先頭文字に d/i/r を持つファイルがなかった。また、サンプルに使ったディレクトリー名がたまたま「dir」で、この除外する条件を満たしてしまっていた。そのため、運良くプログラムが通ってしまった。サンプル・コードで、i や r から始まるファイル、もしくは foo といったディレクトリー名を使っていたら、このやり方が誤っているとすぐに分かったはず。
全く見事なヘマをやってしまった。お恥ずかしい。