コマンドラインで.svnディレクトリを一括削除2008年08月04日 01時05分23秒

DIR コマンドにこんな使い方が

なにを探しているときに見つけたかすでに忘れたのだが、しばらく前にこんなTIPSを見つけた。

タイトルにあるとおり、

dir /b/s somedir
ってやると、UNIX/Linuxのfindコマンドよろしく、指定ディレクトリ以下のファイルをフルパスで列挙してくれる。

例えば、dara-jの手持ちの環境ではZend Framework 1.0.0を D:\PHP\libs\Zend 以下に設置しているのだが、こんな感じで列挙できる。

C:\Documents and Settings\dara-j>dir /b/s D:\PHP\libs\Zend\*.php
D:\PHP\libs\Zend\Acl.php
D:\PHP\libs\Zend\Auth.php
D:\PHP\libs\Zend\Cache.php
D:\PHP\libs\Zend\Config.php
D:\PHP\libs\Zend\Date.php
D:\PHP\libs\Zend\Db.php
D:\PHP\libs\Zend\Debug.php
 :
(中略)
 :
D:\PHP\libs\Zend\XmlRpc\Value\DateTime.php
D:\PHP\libs\Zend\XmlRpc\Value\Double.php
D:\PHP\libs\Zend\XmlRpc\Value\Exception.php
D:\PHP\libs\Zend\XmlRpc\Value\Integer.php
D:\PHP\libs\Zend\XmlRpc\Value\Scalar.php
D:\PHP\libs\Zend\XmlRpc\Value\String.php
D:\PHP\libs\Zend\XmlRpc\Value\Struct.php

C:\Documents and Settings\dara-j>
はぁ、こんなことできたんだぁ。

ヘルプで調べてみると

dir /?でそれぞれのオプションがどんな意味があるのか見てみたところ、

/B ファイル名のみを表示します (見出しや要約が付きません)。
dir /? より抜粋
/S 指定されたディレクトリおよびそのサブディレクトリのすべての ファイルを表示します。
dir /? より抜粋

なるほど、/bで属性などをつけずファイル名(というより、絶対パスみたいなのだが)のみ、/sで再帰処理なことはよくわかった。しかし、何度かこの説明文は見たことあるんだけど、さっぱり気がつかなかった。

その列挙を利用して...

これだけでも割と目から鱗チックだったんだけど、リンク先にはさらにこんなコマンドが載っていた。

リダイレクトしない場合はforコマンドが使えます。

C:\Inetpub\wwwroot> for /f %d in ('dir /b/s _vti_cnf') do rmdir /q/s %d

うーん、よくわからんが、どうやらIISがらみの特定のディレクトリかファイルを再帰処理で一括削除しているみたい。

つか、FORコマンド??

for /?で見てみると(長いヘルプなのでテキストファイルに書き込むと吉)、どうやらこれが該当するのかな。

FOR /F ["オプション"] %変数 IN ('コマンド') DO コマンド [コマンド パラメータ]
for /? より抜粋
説明を見てもなんだか冗長でイマイチ把握しづらいんだけど、()内の一重引用符で囲まれた「dir /b/s _vti_cnf」の結果を変数 %d に逐次当てはめながら、do 以降で指定されているコマンド「rmdir /q/s %d」に渡しているんだろうと。

なるほどねぇ、dir /b/s でファイルのフルパスがあがってくるので、これをforコマンドにまわせばループ処理できるんだ。

.svnディレクトリを再帰的に削除してみたり

んで、やっとこ本題。

Subversionの作業コピーって、各ディレクトリにメタデータディレクトリ「.svn」が隠しディレクトリとして追加されてるのよね。

ローカルで作業してるときはいいんだけど、これをどっかに配布したりするのに、このメタデータが邪魔なので削除してみようかと。いや、当然エクスポートすればいいのは知ってるんだけどね。

いきなり結論。

for /f "tokens=*" %d in ('"dir /b/s/a | findstr /r \.svn$"') do rmdir /q/s "%d"

ここにいたるまで若干の紆余曲折はあったんだけど、要点は以下。
  • dirコマンドには /aオプションもつける → .svnディレクトリが隠し属性だから。
  • .svnディレクトリだけ処理したいので、findstrで「\.svn$」という正規表現で限定してる。もっとうまいやり方あるかな。
  • dir → findstrとパイプでうまくつなげるには二重引用符でくくる。上のコマンドをよーく見てみて。
  • パスに空白が入る場合に対応して、/fの後にオプション「tokens=*」で1行すべてを1トークンとして認識させる
  • 同様に空白対策で、rmdirに渡すときに、%d自体を二重引用符でくくる
特にパイプ処理を通すためにコマンド自体を一重引用符の内側でさらに二重引用符でくくるってのはどうやって見つけたか忘れたけど結構ハマってたりして。

うん、こんな覚えづらいコマンドでちくちくするより「svn export --force work_dir target」したほうがよっぽど速いんだけども。

追記(08.9.7)

svn exportはおいておいて、dirコマンドのオプションでもう少し簡単になりました

コメント

_ babydaemons ― 2009年08月30日 00時30分46秒

丁寧な解説、ありがとうございました。m(_ _)m

_ dara-j ― 2009年08月30日 04時06分31秒

babydaemonsさん

コメントありがとうございます。
てか、まさかネタ元ご本人からお礼されてしまうとは、めっさ恐縮です^^;

あの記事がなかったら、今の快適なFORコマンドライフはなかったので、こちらこそ感謝しております。

_ babydaemons ― 2009年10月18日 09時32分32秒

dara-jさん

> 今の快適なFORコマンドライフはなかったので、こちらこそ感謝しております。

それは良かったです。(^^)/

私もFORコマンド使うときは毎回"FOR /?"しますw

Unixの"man"や"--help"、Windowsの"/?"は基本ですね!

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://dara-j.asablo.jp/blog/2008/08/04/3671839/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。