トップ回答者
How to match certain directory name

質問
-
I wrote a code to examine directories.
I want to skip certain directory using regex.
I wrote
string inputString = d;
string pattern = @".*\\AppData\\Local\\Application Data\\.*";
Match match = Regex.Match(inputString, pattern, RegexOptions.Multiline);
if (match.Success)
{
continue;
}else{
....
}
but seems not working. What's wrong?
回答
-
totojo さん、正規表現パターン内のバックスラッシュのエスケープなので、2つ重ねるのは正しいと思います。
正規表現での処理に問題はなさそうに思いました。
(固定値になっていると OS が変わった時に問題が起きるかもしれないですけど)
intrajp さんの期待通りにならないのはなぜでしょうね。
別の箇所に問題はないでしょうか?
本題からそれてしまいますが、別の方法を考えました。
Application Data などのアクセスできないフォルダは「JUNCTION」と言うものだそうです。
「Error message when you try to access the My Documents, My Music, My Pictures, and My Videos folders in Windows Vista: "Access is Denied"」
http://support.microsoft.com/kb/930128/en
ジャンクションの厳密な判定方法はわかりませんでしたが、とりあえず以下のように判定できそうです。
このように除外されてはいかがでしょうか?
string path = @"C:\Users\Default\AppData\Local";
foreach (string dir in Directory.GetDirectories(path))
{
DirectoryInfo di = new DirectoryInfo(dir);
if (!di.Exists) continue;FileAttributes attributes =
FileAttributes.System | FileAttributes.Hidden | FileAttributes.ReparsePoint;
bool maybeJunction = (di.Attributes & attributes) == attributes;
if (maybeJunction) continue;// 処理
}
一応、元スレッドにリンクしておきますね。
「ファイル検索プログラム作成でアクセス拒否」
http://social.msdn.microsoft.com/Forums/ja-JP/csharpexpressja/thread/d7e23abf-7892-4322-8202-4ce66f90f5e3 -
# 英語は書けないので、そのまま日本語で書きます。
逐語的リテラル文字列 (Verbatim String) はエスケープされないので、これが原因ではないでしょうか?
"pattern" のパスの区切りで、バックスラッシュが2個ずつ入ってしまいます。
文字列の基本 (C# プログラミング ガイド)
http://msdn.microsoft.com/ja-jp/library/ms228362.aspx
(参照: 標準リテラル文字列と逐語的リテラル文字列)
String Basics (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/ms228362.aspx
(See: Regular and Verbatim String Literals)
string pattern = @".*\\AppData\\Local\\Application Data\\.*";
を
string pattern = @".*\AppData\Local\Application Data\.*";
とすると、どうでしょうか?- 回答としてマーク 高橋 春樹 2009年12月8日 9:35
-
そうすると、inputString に渡しているディレクトリ名がフルパスでないとか...。
「@".*\\AppData\\Local\\Application Data\\.*";」なので、"C:\Temp\Backup\AppData\Local\Applocation Data\ABC" も、対象になっちゃうとか。
マルチラインを指定しているので、その辺が悪さしているとか。
それと、終わりの ".*" は、いらないと思います。
Application Data などのアクセスできないフォルダは「JUNCTION」と言うものだそうです。
一応、元スレッドの方に書いているんだけどね。
Jitta@わんくま同盟- 回答としてマーク 高橋 春樹 2009年12月8日 9:36
-
私は問題なさそうと書きましたが、totojo さんが指摘されているように、最後のバックスラッシュはいらなさそうですね。
Jitta さん
> それと、終わりの ".*" は、いらないと思います。
親フォルダが対象外になれば、子フォルダの判定は不要ということですね。
「問題ない」と書いて問題があれば迷惑になるのでよく見直してたのですが、気づきませんでした。
お二人のを合わせると、
string pattern = @".*\\AppData\\Local\\Application Data";
で良いことになります。
もしバックスラッシュの有無に依存せず、子フォルダまでも判定する場合は次のパターンになります。
string pattern = @".*\\AppData\\Local\\Application Data(\\?|\\.*)";
1つ目のパターンで良い場合、正規表現は使わずに
if ((inputString ?? "").EndsWith(@"\AppData\Local\Application Data")) continue;
という判定でも良さそうです。
Jitta さん
> 一応、元スレッドの方に書いているんだけどね。
読みのがしてました。。 -
> 一応、元スレッドの方に書いているんだけどね。
読みのがしてました。。
誤解させたようで、ごめんなさい。TH01さんに対して何か言っているわけではありません。「何故アクセスできないか」について、原因を書いているのに、その原因を吟味していない質問者さんに対しての苦言です。
string pattern = @".*\\AppData\\Local\\Application Data";
で良いことになります。“
string pattern = @"[a-zA-Z]:\\AppData\\Local\\Application Data";
”かと。先に書いたように、".*" だと「任意の文字が任意の数」です。元スレッドを合わせると、ここはドライブ ルートからのパスだと思います。
面倒なのでこっちにくっつけときます。
あと、もしシステムフォルダも検索するとしたら、方法はないのでしょうか?
Windows Service にして、LOCAL SYSTEM で動かせば可能かと思います。
しかし、SYSTEM にしか書き込みできないところに、任意のユーザーが書き込みすることは出来ない=そんなところにファイルはない(あってもシャドー コピー)と思います。
Jitta@わんくま同盟- 回答としてマーク 高橋 春樹 2009年12月8日 9:36
すべての返信
-
# 英語は書けないので、そのまま日本語で書きます。
逐語的リテラル文字列 (Verbatim String) はエスケープされないので、これが原因ではないでしょうか?
"pattern" のパスの区切りで、バックスラッシュが2個ずつ入ってしまいます。
文字列の基本 (C# プログラミング ガイド)
http://msdn.microsoft.com/ja-jp/library/ms228362.aspx
(参照: 標準リテラル文字列と逐語的リテラル文字列)
String Basics (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/ms228362.aspx
(See: Regular and Verbatim String Literals)
string pattern = @".*\\AppData\\Local\\Application Data\\.*";
を
string pattern = @".*\AppData\Local\Application Data\.*";
とすると、どうでしょうか?- 回答としてマーク 高橋 春樹 2009年12月8日 9:35
-
totojo さん、正規表現パターン内のバックスラッシュのエスケープなので、2つ重ねるのは正しいと思います。
正規表現での処理に問題はなさそうに思いました。
(固定値になっていると OS が変わった時に問題が起きるかもしれないですけど)
intrajp さんの期待通りにならないのはなぜでしょうね。
別の箇所に問題はないでしょうか?
本題からそれてしまいますが、別の方法を考えました。
Application Data などのアクセスできないフォルダは「JUNCTION」と言うものだそうです。
「Error message when you try to access the My Documents, My Music, My Pictures, and My Videos folders in Windows Vista: "Access is Denied"」
http://support.microsoft.com/kb/930128/en
ジャンクションの厳密な判定方法はわかりませんでしたが、とりあえず以下のように判定できそうです。
このように除外されてはいかがでしょうか?
string path = @"C:\Users\Default\AppData\Local";
foreach (string dir in Directory.GetDirectories(path))
{
DirectoryInfo di = new DirectoryInfo(dir);
if (!di.Exists) continue;FileAttributes attributes =
FileAttributes.System | FileAttributes.Hidden | FileAttributes.ReparsePoint;
bool maybeJunction = (di.Attributes & attributes) == attributes;
if (maybeJunction) continue;// 処理
}
一応、元スレッドにリンクしておきますね。
「ファイル検索プログラム作成でアクセス拒否」
http://social.msdn.microsoft.com/Forums/ja-JP/csharpexpressja/thread/d7e23abf-7892-4322-8202-4ce66f90f5e3 -
そうすると、inputString に渡しているディレクトリ名がフルパスでないとか...。
「@".*\\AppData\\Local\\Application Data\\.*";」なので、"C:\Temp\Backup\AppData\Local\Applocation Data\ABC" も、対象になっちゃうとか。
マルチラインを指定しているので、その辺が悪さしているとか。
それと、終わりの ".*" は、いらないと思います。
Application Data などのアクセスできないフォルダは「JUNCTION」と言うものだそうです。
一応、元スレッドの方に書いているんだけどね。
Jitta@わんくま同盟- 回答としてマーク 高橋 春樹 2009年12月8日 9:36
-
私は問題なさそうと書きましたが、totojo さんが指摘されているように、最後のバックスラッシュはいらなさそうですね。
Jitta さん
> それと、終わりの ".*" は、いらないと思います。
親フォルダが対象外になれば、子フォルダの判定は不要ということですね。
「問題ない」と書いて問題があれば迷惑になるのでよく見直してたのですが、気づきませんでした。
お二人のを合わせると、
string pattern = @".*\\AppData\\Local\\Application Data";
で良いことになります。
もしバックスラッシュの有無に依存せず、子フォルダまでも判定する場合は次のパターンになります。
string pattern = @".*\\AppData\\Local\\Application Data(\\?|\\.*)";
1つ目のパターンで良い場合、正規表現は使わずに
if ((inputString ?? "").EndsWith(@"\AppData\Local\Application Data")) continue;
という判定でも良さそうです。
Jitta さん
> 一応、元スレッドの方に書いているんだけどね。
読みのがしてました。。 -
> 一応、元スレッドの方に書いているんだけどね。
読みのがしてました。。
誤解させたようで、ごめんなさい。TH01さんに対して何か言っているわけではありません。「何故アクセスできないか」について、原因を書いているのに、その原因を吟味していない質問者さんに対しての苦言です。
string pattern = @".*\\AppData\\Local\\Application Data";
で良いことになります。“
string pattern = @"[a-zA-Z]:\\AppData\\Local\\Application Data";
”かと。先に書いたように、".*" だと「任意の文字が任意の数」です。元スレッドを合わせると、ここはドライブ ルートからのパスだと思います。
面倒なのでこっちにくっつけときます。
あと、もしシステムフォルダも検索するとしたら、方法はないのでしょうか?
Windows Service にして、LOCAL SYSTEM で動かせば可能かと思います。
しかし、SYSTEM にしか書き込みできないところに、任意のユーザーが書き込みすることは出来ない=そんなところにファイルはない(あってもシャドー コピー)と思います。
Jitta@わんくま同盟- 回答としてマーク 高橋 春樹 2009年12月8日 9:36
-
フォーラムオペレーターの高橋春樹です。
totojoさん、TH01さん、Jittaさん、こんにちは。
アドバイスありがとうございました。intrajpさん、こんにちは。
MSDNフォーラムのご利用ありがとうございます。皆さんからのアドバイスが、疑問点の解決に繋がったようで、よかったです。
今回、totojoさん、TH01さん、Jittaさんからの投稿が、有用な情報だと思いましたので、
勝手ながら、こちらで回答マークを付けさせてもらいました。
次回からでよいのですが、疑問点が解決した場合、お礼も兼ねて参考になったと思われる投稿に、
回答マークを付けて貰いたいと思います。今後ともMSDNフォーラムをよろしくお願いします(^_^)
マイクロソフト株式会社 フォーラム オペレーター 高橋春樹