2012-04-21

カレント・ディレクトリー内の全てのファイルを新しい下位ディレクトリーに簡単に移動させる 〜 zsh 編 その二

の続き。前の記事で、ディレクトリー「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 といったディレクトリー名を使っていたら、このやり方が誤っているとすぐに分かったはず。

全く見事なヘマをやってしまった。お恥ずかしい。

ref

No comments:

Post a Comment