アカウント名:
パスワード:
皆様、ありがとうごさいました。-fはスペースの入ったファイル名でも問題はありませんでした。
作っていたスクリプトの open (MD5,"md5sum $filename |")のところで、$filenameが"file space"では上手く行かなかったのを-fの問題だと勘違いしました。大変お騒がせ致しました。失礼いたしました。
つまり、"file space"というファイルがあり、$filenameが "file space"の時、-f $filenameはtrueになるが、open (MD5,"md5sum $filename |")ではエラーになるということでした。
$filenameが"file\ space"ならば md5sumでもOK。
すでに自力で答を得ているかもしれませんが御参考までに。
$filename = "file space";open (MD5,"md5sum $filename |");
のような2引数のopenでパイプを作ると次のように動きます。 1. Perlが変数$filenameを展開。("md5sum file space |") 2. Perlが末尾のパイプ記号を見て、残りを/bin/shに渡す。("md5sum file space") 3. /bin/shが文字列を空白で区切る。("md5sum", "file", "space") 4. /bin/shが"md5sum"を探して引数("md5sum", "file", "space")を渡す。 5. md5sumが引数を見て"file"と"space"のMD5を計算しようとする。
Perlが/bin/sh経由でmd5sumを実行するので、 空白に限らず、/bin/shの特殊文字が意味を持ってしまいます。
例えば、カレントディレクトリの全ファイルのMD5を計算しようとして、
#!/usr/bin/perl --# 注: 危険なスクリプトforeach my $filename (<*>) { open(MD5, "md5sum $filename |"); print <MD5>; close(MD5);}
なんてスクリプトを使ってしまうと、例えばカレントディレクトリに、
$ touch "<'file space'|rm -rf *"
なんてやって変な名前のファイルを仕込まれていた場合に泣きます。 良い子は真似しないでね。
話を戻すと、そもそもPerlが/bin/sh経由でmd5sumを呼び出すのが悪いので、 もっと安全にパイプコマンドを作れば良いのです。 では、どうするか? 悩んだらマニュアルを読みましょう。RTFM!! この場合はopenで悩んでいるので、
$ perlfunc -f open
とかやって読みます。するとパイプの説明で盛んに「perlipcを読め」と書いてあるので、そっちも読みます。
$ man perlipc
すると"Safe Pipe Opens"節に、 shellに邪魔されない方法が色々書いてあります。好きなやり方を選びましょう。TMTOWTDI.
Ubuntu 11.10ならこんな感じで動くはず。
open(MD5, "-|", "md5sum", $filename)
ちなみにsystemとかbacktick(qx//または``)とかも同様の問題を孕んでおり、 解決策も似ているので以下RTFM。
では引き続きPerlプログラミングをお楽しみ下さい。enjoy!
Shellを通さない方法のご紹介ありがとうございました。
先ほどまで、\,(,),[,],$,|,その他をエスケープするようにコードを組み込んでいました。'と'で挟んでもファイル名が'を含むとうまく行きません。そんな変態なファイル名のファイルを作る人はいないと思いますが。
やはり、このようなことが不要な正しい方法があるのですね。やや新しいPerlの機能なのかな。
大変参考になりました。
そこでファイル名をクォートしなければいけないのは当たり前だろ。md5sumに限らずコマンドライン引数にファイル名を指定するほとんどどんなプログラムでもまったく同じ話なのに「問題だったのはmd5sum」って…。自分ではない何かのせいにしないと気がすまないの? md5sumは超能力で意図を検知して動作しろとでも?
まあ、おっしゃるとおりなんですが、実際にスクリプトを作っている時には、md5sumに渡すときはスペースをエスケープしていて、その時、-fでもそのまま上手く行くはずだと思い込んでしまったのが勘違いのもとだったみたいです。失礼しました。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
物事のやり方は一つではない -- Perlな人
すいません勘違いでした。問題だったのはmd5sumでした (スコア:1)
皆様、ありがとうごさいました。
-fはスペースの入ったファイル名でも問題はありませんでした。
作っていたスクリプトの
open (MD5,"md5sum $filename |")
のところで、$filenameが"file space"では上手く行かなかったのを-fの問題だと勘違いしました。大変お騒がせ致しました。失礼いたしました。
つまり、
"file space"というファイルがあり、
$filenameが "file space"の時、
-f $filenameはtrueになるが、
open (MD5,"md5sum $filename |")
ではエラーになるということでした。
$filenameが"file\ space"ならば md5sumでもOK。
Re:すいません勘違いでした。問題だったのはmd5sumでした (スコア:1)
すでに自力で答を得ているかもしれませんが御参考までに。
のような2引数のopenでパイプを作ると次のように動きます。
1. Perlが変数$filenameを展開。("md5sum file space |")
2. Perlが末尾のパイプ記号を見て、残りを/bin/shに渡す。("md5sum file space")
3. /bin/shが文字列を空白で区切る。("md5sum", "file", "space")
4. /bin/shが"md5sum"を探して引数("md5sum", "file", "space")を渡す。
5. md5sumが引数を見て"file"と"space"のMD5を計算しようとする。
Perlが/bin/sh経由でmd5sumを実行するので、 空白に限らず、/bin/shの特殊文字が意味を持ってしまいます。
例えば、カレントディレクトリの全ファイルのMD5を計算しようとして、
なんてスクリプトを使ってしまうと、例えばカレントディレクトリに、
なんてやって変な名前のファイルを仕込まれていた場合に泣きます。 良い子は真似しないでね。
話を戻すと、そもそもPerlが/bin/sh経由でmd5sumを呼び出すのが悪いので、 もっと安全にパイプコマンドを作れば良いのです。 では、どうするか? 悩んだらマニュアルを読みましょう。RTFM!! この場合はopenで悩んでいるので、
とかやって読みます。するとパイプの説明で盛んに「perlipcを読め」と書いてあるので、そっちも読みます。
すると"Safe Pipe Opens"節に、 shellに邪魔されない方法が色々書いてあります。好きなやり方を選びましょう。TMTOWTDI.
Ubuntu 11.10ならこんな感じで動くはず。
ちなみにsystemとかbacktick(qx//または``)とかも同様の問題を孕んでおり、 解決策も似ているので以下RTFM。
では引き続きPerlプログラミングをお楽しみ下さい。enjoy!
Re:すいません勘違いでした。問題だったのはmd5sumでした (スコア:1)
shellを通さない方法ありがとうございました (スコア:1)
Shellを通さない方法のご紹介ありがとうございました。
先ほどまで、\,(,),[,],$,|,その他をエスケープするようにコードを組み込んでいました。'と'で挟んでもファイル名が'を含むとうまく行きません。そんな変態なファイル名のファイルを作る人はいないと思いますが。
やはり、このようなことが不要な正しい方法があるのですね。やや新しいPerlの機能なのかな。
大変参考になりました。
Re: (スコア:0)
そこでファイル名をクォートしなければいけないのは当たり前だろ。md5sumに限らずコマンドライン引数にファイル名を指定するほとんどどんなプログラムでもまったく同じ話なのに「問題だったのはmd5sum」って…。自分ではない何かのせいにしないと気がすまないの? md5sumは超能力で意図を検知して動作しろとでも?
Re:すいません勘違いでした。問題だったのはmd5sumでした (スコア:1)
まあ、おっしゃるとおりなんですが、実際にスクリプトを作っている時には、md5sumに渡すときはスペースをエスケープしていて、その時、-fでもそのまま上手く行くはずだと思い込んでしまったのが勘違いのもとだったみたいです。失礼しました。