パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

[質問] Perlのファイル検査 -f とスペースの入ったファイル名」記事へのコメント

  • 皆様、ありがとうごさいました。
    -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!

      親コメント

あつくて寝られない時はhackしろ! 386BSD(98)はそうやってつくられましたよ? -- あるハッカー

処理中...