6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPでコマンドを実装してみる cat篇

Posted at

にゃーん

これまでのあらすじ

catコマンドってなんだ

複数のファイルを連結して標準出力するのがcatコマンド。

% cat ./hoge #hogeファイルの中身を標準出力する
ほげ
% cat ./hoge ./huga ./piyo > ./xxx #ファイルを連結してxxxファイルに書き込む
% cat ./xxx
ほげ
ふが
ぴよ
% echo んー | cat # パイプで渡して引数なし
んー
% echo んー | cat - - - # - が標準入力
んー
んー
んー

要件としては、こんな感じ…?

実装

引数なしのときは標準入力のみを出力。標準入力はキャッシュする。

あと、ファイルがなかったりしたら標準エラー出力に書き込む。

fwrite(STDERR, "cat: ${f}: No such file or directory" . PHP_EOL);

文言は例によってBSD catから拝借してる。読み込めないファイルがひとつでもあったとき、終了ステータスは1にする。

完成

#!/usr/bin/env php
<?php
namespace zonuexe\UnixCommand;

/**
 * CAT command
 *
 * @author    USAMI KENTA <tadsan@zonu.me>
 * @license   http://www.apache.org/licenses/LICENSE-2.0 Apache-2.0
 * @copyright 2015 USAMI Kenta
 */

if (realpath($_SERVER['SCRIPT_FILENAME']) == realpath(__FILE__)) {
    $argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : [];
    array_shift($argv);

    exit(cat($argv));
}

/**
 * @return int UNIX status code
 */
function cat(array $argv)
{
    $files  = $argv ?: ['-'];
    $failed = false;
    $stdin  = null;

    foreach ($files as $f) {
        $file = null;
        if ($f === '-') {
            if ($stdin !== null) {
                echo $stdin;
                continue;
            }

            $file = STDIN;
        } elseif (!is_file($f)) {
            $failed = true;
            fwrite(STDERR, "cat: ${f}: No such file or directory" . PHP_EOL);
            continue;
        } else {
            $file = fopen($f, 'r');
        }

        while (!feof($file)) {
            $data = fread($file, 8192);
            if ($data === false) {
                break;
            }
            if ($f === '-') {
                $stdin .= $data;
            }

            echo $data;
        }
        fclose($file);
    }

    return $failed ? 1 : 0;
}

感想

今回は標準入出力を扱ったり終了ステータスを扱ったり、ちゃんとUnixコマンドっぽい感じになりましたね。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?