▼スレッド
│
└◇1288:locateでWindows上の全領域を検索したい [あき] 06/28 00:48
└◇1290:Re:locateでWindows上の全領域を検索したい [MSだす。] 06/29
└◇1292:Re[2]:locateでWindows上の全領域を検索したい [nil] 06/30
├◇1297:Re[3]:locateでWindows上の全領域を検索したい [knabe] 07/01
│└◇1298:Re[4]:locateでWindows上の全領域を検索したい [MSだす。] 07/01
│ └◇1299:Re[5]:locateでWindows上の全領域を検索したい [knabe] 07/01
│ ├◇1300:Re[6]:locateでWindows上の全領域を検索したい [あき] 07/01
│ │├◇1302:Re[7]:locateでWindows上の全領域を検索したい [あき] 07/01
│ │└◇1304:Re[7]:locateでWindows上の全領域を検索したい [nil] 07/02
│ │ └◇1305:Re[8]:locateでWindows上の全領域を検索したい [nil] 07/02
│ └◇1303:Re[6]:locateでWindows上の全領域を検索したい [nil] 07/02
│ └◇1306:Re[7]:locateでWindows上の全領域を検索したい [knabe] 07/02
│ └◇1312:Re[8]:locateでWindows上の全領域を検索したい [nil] 07/02
└◇1327:Re[3]:locateでWindows上の全領域を検索したい [nil] 07/06
└◇1330:Re[4]:locateでWindows上の全領域を検索したい [nil] 07/08
├◇1332:Re[5]:locateでWindows上の全領域を検索したい [nil] 07/09
└◇1341:Re[5]:locateでWindows上の全領域を検索したい [あき] 07/13 <
はじめまして。スレッド一覧
locate(1)でのファイル検索対象にC:\cygwin以外のWindowsのディレクトリを追加したいと思っています。
試しに
$ updatedb --localpaths='/cygdrive/c/'
とやってみたところ、日本語を含むディレクトリ名(例えばDocuments and Settings/All Users/スタート メニュー)のところでエラーが出てしまいます。
エラーの内容は次のとおりです。
/usr/bin/find: /cygdrive/c/Documents and Settings/All Users/スタート メニュー:No such file or directory
$ updatedb --localpaths='"/cygdrive/c/"'
とか
$ env IFS=',' updatedb --localpaths='/cygdrive/c/'
等いろいろ試してみたのですがうまくいきません。
対処方法をご存知の方いましたら教えてください。
よろしくお願いします。
スレッド一覧
WinXP HOME SP1
cygwin 1-3-22
ですが、そのエラーがでません…。
$ updatedb --output=locatedb.ALL --localpaths='/cygdrive/c'
(いくつか、Permission denied、No such file or directoryのエラーが
出ますが、日本語とは関係ありません)。
その後、
$ locate -d locatedb.ALL お悔み
/cygdrive/c/Program Files/Microsoft Office/Templates/1041/お悔みのお礼.dot
…
などと出て来ます。ただなぜか明示的に--localpaths='/cygdrive/c /cygdrive/c/WINDOWS'
としないとc:\WINDOWSを見に行ってくれみたいですね。
何か他にオプション指定してませんか?
あるいは日本語に関してどのような設定をしているのでしょうか?
スレッド一覧
これも私が困ったのと同じ問題のような気が…
Win2k,XP + Cygwin 1.3.22-1 の VFAT上(^^;)の話ですが、Shift-JIS の
場合に漢字の 2byte目が '\\'(backslash) の文字を含む名前のディレク
トリがあると発生するようです。NTFS では試したことがありません。
mkdir -p 'C:/test/t0'; touch 'C:/test/t0/ソフト'
mkdir -p 'C:/test/t1/ソフトABC'
mkdir -p 'C:/test/t2/ABCソフト'
mkdir -p 'C:/test/t3/ABCソ'
for n in 0 1 2 3 ; do find C:/test/t$n -print; done
自分で漢字ファイル(ディレクトリ)名を使うことが少ないので、はじめ
は気がつかなかったのですが、いまさらながら multi-byte の扱いにい
ろいろ問題があるようで苦笑しました。
(上記のようなディレクトリを rm -rf するとコマンドが終了しない、等)
最近、Cygwin JE などという本で日本語環境に触れているらしいのです
が、参考になるかもしれません。私は未見です。
Cygwin とは別の find を使うとか(Win32版GNU や NT utils ?)、いろい
ろ誤魔化し方はあるとは思います。
locate だけで良いのならば、updatedb を改造して、find を使わず別の
手順でlist を生成してから、locate DataBase を作っても良いでしょう。
どうやら ruby では上記のような問題を回避しているようです。ruby を
知らないので次のようなでっちあげしか試してませんが。
ruby -Ks -rfind -e 'Find.find("C:/foo") do |f|; print "#{f}\n"; end'
(perl 5.8 ではどうするのがよいのか思いつかなかった。find2perl だ
けでは駄目そうなのですがどうでしょうか?)
根本的には Cygwin の国際化(?日本語化)がまだ不十分で SJIS locale
だけでは対応できないような気がしているのですが、実装を知らないの
で私の勘違いかもしれません。識者の方、どうなんでしょう?
(前、MinGW で find を compile すればどうなるかと思ったのですが、
少なくとも Cygwin の MinGW では足りないものがあるようです。)
#思わず長くなりましたが…
うちではこんなものを使っています:スレッド一覧
http://www.page.sannet.ne.jp/knabe/cygwin/localize.html
1.3.22 on NT5.0, Win98SEでここ数ヶ月使用しています。
# ライセンスの面倒を避けるためにパッチだけですが。
# ローカライズにしても汚なすぎるので、upstreamへのマージは行いません。
nilさんが試してみたように、cygwin1.dll内部のディレクトリ検索処理に
問題があるため、cygwin環境の内部からでは対処できません。
# '発表' とか '二十' とかのディレクトリを作るとよく分かります。
native win32のツールを併用するか、cygwin1.dllにパッチをあてる以外の
策はないと思います。
# MSだす。さんの環境で問題が出ないのは逆に不思議ですが。
もちろん何かと日本語…特にSJISでは…トラブルがスレッド一覧
起きるのは知っていますが、何はともあれ"スタート メニュー"
はデータに入っています…。
ところで、試しに"発表二十"(なんだそりゃ)という
フォルダをエクスプローラから作り、updatedbしてみました。
$ updatedb --output=testdb --localpaths='.'
/usr/bin/find: ./発表二十: No such file or directory
$locatedb -d testdb '発表'
./発表二十
$
今度はエラーが出ましたが、データファイルには
登録されたようです。
ただし、そのフォルダの中は見に行ってくれません。
なお、私は習慣的にめったなことでは日本語のファイル、
フォルダ名は使っていません。それでエラーが出なかったのでしょう。
しかし、スタート メニューでは問題がおきせんでした。
先に作った"locatedb.ALL"で、
$ locate -d locatedb.ALL 'ス'
…
/cygdrive/c/Documents and Settings/Administrator/スタート メニュー/プログラム/In
ternet Explorer.lnk
/cygdrive/c/Documents and Settings/Administrator/スタート メニュー/プログラム/Ou
tlook Express.lnk
…
などと出てきます。
すみません。わたしの勘違いです。スレッド一覧
標準の状態では、 'スタートメニュー' 以下に引掛るディレクトリはありませんね。
ただそうすると、最初にあきさんが示したエラーが発生する理由がわからない。
皆様どうもありがとうございます。スレッド一覧
結局updatedbがうまくいかなかった原因は、
「ディレクトリ名の中にシフトJISで2バイト目に'\'(0x5c)がを含む文字があると、
それがバックスラッシュと誤認されてしまいfindがうまく機能しない」
ということですね。
私は恥ずかしながら今回初めて知ったのですが、
この問題自体は文字コードの分野ではよく知られていることのようですね。
#UTF-8はこの点を改善したものだとか。
(参考)http://euc.jp/i18n/charcode.ja.html
さて、nilさんのアドバイスに従って下記のコマンドを実行してみました。
mkdir -p 'C:/test/t0'; touch 'C:/test/t0/ソフト'
mkdir -p 'C:/test/t1/ソフトABC'
mkdir -p 'C:/test/t2/ABCソフト'
mkdir -p 'C:/test/t3/ABCソ'
for n in 0 1 2 3 ; do find C:/test/t$n -print; done
すると結果は、
C:/test/t0
C:/test/t0/ソフト
C:/test/t1
C:/test/t1/ソフトABC
C:/test/t2
C:/test/t2/ABCソフト
find: C:/test/t2: No such file or directory
C:/test/t3
C:/test/t3/ABCソ
find: C:/test/t3: No such file or directory
となりました。
あれ??
2バイト目に0x5cを含む文字とは次のような文字だそうですが、
http://www.hidecnet.ne.jp/~sinzan/tips/etc/etc_tip01.htm
なぜ「ソ」を含むのにt0やt1にfindのエラーが出ないんでしょうか?
私の理解が不十分で申し訳ないのです。
また、「MSだす。さん」や、「knabeさん」のコメントにもあったように
本題の方の
/cygdrive/c/Documents and Settings/All Users/スタート メニュー
でエラーが出るのもいまだよく分かりません。
よろしかったら教えてください。
すいません訂正です。スレッド一覧
実行結果は
C:/test/t0
C:/test/t0/ソフト
C:/test/t1
C:/test/t1/ソフトABC
C:/test/t2
C:/test/t2/ABCソフト
find: C:/test/t2: No such file or directory
C:/test/t3
C:/test/t3/ABCソ
find: C:/test/t3/ABCソ: No such file or directory
~^^^^^^^^
です。
なぜ、t2の方はエラー表示が C:/test/t2 までで
t3のほうは C:/test/t3/ABCソ までで表記させているのでしょう?
スレッド一覧
t1,t3 の結果が違いますね。こちらでは(VFAT)こうなります。
NTFS だと違うのですかね? どなたか教えてください。
(NTFSをすぐに用意できない貧乏)
C:/test/t0
C:/test/t0/ソフト
C:/test/t1
C:/test/t1/ソフトABC
find: ./.. changed during execution of find
C:/test/t2
C:/test/t2/ABCソフト
find: C:/test/t2: No such file or directory
C:/test/t3
C:/test/t3/ABC
t3 の 'ABCソ' は、ls したほうがわかりやすいのですが、最後の
byteが '\\' だった場合、'ABC' しか作られない、という現象の
テストのつもりでした。
が、結果が違いますね。
t0 でエラーが出ないのは、ディレクトリ名ではなくて、ファイル
名だからです。
"スタート メニュー" でエラーが出るのは、その *下* に問題の
ディレクトリ(フォルダ) があるはず(?)だからです。
>C:/test/t2/ABCソフト
>find: C:/test/t2: No such file or directory
での警告が "C:/test/t2/ABCソフト" でなく "C:/test/t2" なの
にご注意ください。
>での警告が "C:/test/t2/ABCソフト" でなく "C:/test/t2" なのスレッド一覧
>にご注意ください。
念の為。これ、警告が正しいわけではなく、ようするにすでに
警告も変だと。find だか Cygwin の内部処理に問題がありそうと
推測するわけです。
スレッド一覧
ええと、たぶん、"スタート メニュー" の *下* にはいろいろな
物が勝手に作られてしまいますから… メーカ製のPCだともとから
余計なものがはいっているし。
私も主にOEMでないWinを使うことが多いので、はじめは気がつか
ないで平気で find C:/ などとしていました。へんなこともあり
ましたが、自分では、漢字のfile, dir名を作らないので致命的な
問題はなかった。
うかつといえばうかつです。WXP のメーカ製のNote-PCを標準(?)
状態に近いまま使った時に不具合に気がつきました。
"スタート メニュー" の *下* に "VxxOソフトウェアはこちら"
なんてフォルダがある(^^;)。
# MSが意識的に '\\' を避けたわけでもあるまいが :-p
>http://www.page.sannet.ne.jp/knabe/cygwin/localize.html
おお、前に見たような気がしたのを見つけられないでいたのでした。
ありがとうございます。
ところで、この手の問題はFAQ等としてどこかにまとまっていたのでしょうか?
ご存知でしたら参照先でも教えていただけませんでしょうか。
以前にもちょこちょこっと探したのですが予想以上に見つからなかったので。
どうも周知だったというわけでもないようですし。
久々に素のcygwin1.dllに戻して、straceかけてみて納得。スレッド一覧
# for n in 0 1 2 3; do strace -o ~/find.$n.trace find t$n -print; done
原因はnormalize_posix_path()でコードページを無視して
無条件に0x5c(\)を0x2f(/)に変換しているためです。
このためにSJIS第二バイトに0x5cを含む文字('ソ'など)が
破壊され、"ABCソフト"が"ABC(0x83)/フト"となってしまい、
エラーが発生します。
# エラーメッセージが変な原因は忘れました。
なお、t3では、opendir()でディレクトリの中身を検索す
るために渡されたパスに'\*'を付加してFindFirstFileA()を
呼んでいるところで、パス名の末尾の文字が0x5cだった場合
には、'*'しかつけていないことも影響します。
問題はcygwin1.dllの内部でFindFirstFileA()のようにANSI
コードページをパス名として受け取るWin32APIを使っている
のに、ANSIコードページを無視して文字列処理を行っている
あたりにあるような気がします。
# FindFirstFileW()のようなワイドキャラクタ(Windowsの実装
# では実体はUnicode)を受け取るAPIを使うか、藤枝さんのi18n
# 拡張のようにISO Cのワイドキャラクタ関連を実装するしか
# ないと思いますが、どちらにしても範囲が大きい...
このあたりの問題は、文書としてまとまったものはないと
思います。
# 皆さん問題を避けて使っているみたいで。
スレッド一覧
なるほど、勉強になりました。(strace の出力を刈り込む気力が無くて追ってま
せんでした。Win32APIはまったく知らないので src. を見ていないし)
|# FindFirstFileW()のようなワイドキャラクタ(Windowsの実装
|# では実体はUnicode)を受け取るAPIを使うか、藤枝さんのi18n
|# 拡張のようにISO Cのワイドキャラクタ関連を実装するしか
|# ないと思いますが、どちらにしても範囲が大きい...
藤枝さんの情報以前見つからなかったのですが、今探すと分かりました。
Cygwin ではいまだに考慮されてないわけですね…
|# 皆さん問題を避けて使っているみたいで。
まあ、私も誤魔化しながらもブツブツと使ってますね。
最近、MSYS + WIn32 GNU とのどちらが幸せか考え始めたりして。
文書としてまとまっている、というより SJIS がらみの FAQ なり警告
は、一般には知られているのでしょうかね。問題に気がつかないまま使っ
ている人も多いような気がしてちょっと怖い。
どうもお手数をおかけしました。
すいません、うそでした。前出の Cygwin版 ruby の Find でも、スレッド一覧
GnuWin32版も、ディレクトリ名の最後のバイトが 0x5c(\) の場合には
正常に動いていませんでした。
("ABCソフト"は正常、"ABCソ" は異常処理)
#てっきり Win32版GNU などでは multi-byte の API 使ってそう、など
#と思い込んでたようで。
MSWIN32版の ruby 1.6.8 ではこの問題は大丈夫のようです。
(また確認不足かもしれないけど)
Vector などにある UNIX-like tools (オリジナル or NT版) でも大丈
夫ですが、find として bash 上から使うには引数のエスケープの仕方
で使いにくい面があるようです。
ということで、find を置き換えるのに都合の良いものが無くなってし
まった様な…
とりあえず。
-- 正常
$ cmd.exe /c dir /b /s 'C:\test\r'
C:\test\r\r0
C:\test\r\r1
C:\test\r\r0\ABCソフト
C:\test\r\r0\ABCソフト\ABC.txt
C:\test\r\r1\ABCソ
C:\test\r\r1\ABCソ\ABC.txt
-- NG
# Cygwin
$ find C:/test/r -print
...
find: C:/test/r/r0: No such file or directory
# ruby 1.6.8 on Cygwin
$ ruby -Ks -rfind -e 'Find.find("C:/test/r") do |n|; print "#{n}\n"; end'
...
C:/test/r/r1/ABCソ/ABCソ
# GnuWin32
$ find C:/test/r -print
...
C:/test/r/r1/ABCソ
find: C:/test/r/r1/ABCソ/ABCソ: No such file or directory
結局、find を置き換える適当な実装を紹介できなかったですね。スレッド一覧
他の問題も解決できる事を考えると、knabe さんの SJIS用パッチを使
うのがよいのでしょうが、これは一般に勧めるのはちょっと考えてしま
いますね。どうでしょ?
意識していなければ、update で気づかずに上書きしてしまう人も少な
くなさそうですし。
バイナリ配布が無さそう(?)なのは自己責任で使えるかた向け、という
のは勘ぐり過ぎでしょうか。
それで、元のお話が locate が使えるだけでよい、ということならば、
updatedb の代わりに使えるスクリプトを無理矢理作ってみました。
(他に NT版UNIX-like tools の findf.c を修正して、-mno-cygwin で
/lib/mingw/CRT_noglob.o をlinkさせればなんとかなります)
libiconv, libiconv2 のインストールが必要です。
sort の前後どちらかで EUCから SJISへの変換を行って良いかどうかは
テストしてません。
# Windows の検索機能をコマンドライン・インターフェイスで使うよう
#なツールってあるのですかね。VB script か何かで組めないのかな?
--- updatedb-simple BEGIN
#!/bin/sh -
# replace simple updatedb
# Your config.
DIRS='C:\ D:\'
#DIRS='C:\tmp'
: ${LOCATE_DB=/usr/var/locatedb}
: ${LIBEXECDIR=/usr/sbin}
: ${frcode=${LIBEXECDIR}/frcode}
s2e() { iconv -f CP932 -t eucJP; }
e2s() { iconv -f eucJP -t CP932; }
#-s2e() { nkf -xed; }; e2s() { nkf -xsd; }
findall() { for d; do CMD.EXE /C DIR /B /S "$d"; done | fix2unix; }
fix2unix() { s2e | dos2unix | tr '\\' '/'; }
#fix2unix() { s2e | dos2unix | sed -e 's@\\@/@g;s@^\(.\):@/cygdrive/\1@'; }
xsort() { sort -f | e2s; }
#xsort() { e2s | sort -f; }
#xsort() { sort -f; }
findall $DIRS | xsort | $frcode > $LOCATE_DB.n
if [ -s $LOCATE_DB.n ]; then
rm -f $LOCATE_DB
mv $LOCATE_DB.n $LOCATE_DB
else
rm -f $LOCATE_DB.n
fi
exit
--- END
忘れてました。あくまでも簡易版なので使用した結果を保障しません。スレッド一覧
隠れたファイル表示させるのを忘れてました。
また dir C:/foo だと find と違って DIR 自身を出力しません。
修正は findall() の定義を下記の2行に変更してください。
findall0() { for d; do printf '%s\r\n' "$d"; CMD /C DIR/B/A/S "$d"; done; }
findall() { findall0 | fix2unix; }
アドバイスいただいた皆様ありがとうございました。スレッド一覧
当初はlocateがcygwin以外の領域に使えれば便利だなと思っただけだったのですが、
いい機会ですので、nilさんのスクリプトやknabeさんのパッチ等を使わせていただくのに加えて、
WindowsやUNIXにおける日本語の扱い等をもう少し勉強してみようと思います。