Skip to content

Commit

Permalink
Improved STDIN support, added examples
Browse files Browse the repository at this point in the history
  • Loading branch information
kamermans committed Dec 17, 2014
1 parent 5ddaf43 commit 52443d7
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 3 deletions.
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,59 @@ $cmd = Command::factory('grep CRON < /var/log/syslog | head', true)
->run();
```

## Using STDIN
You can provide data for STDIN using a string or a stream resource (like a file handle)

### STDIN from a String

```php
use kamermans\Command\Command;

$stdin = "banana
orange
apple
pear
";

$cmd = Command::factory("sort")
->run($stdin);

echo $cmd->getStdOut();
```

### STDIN from a Stream

```php
use kamermans\Command\Command;

$filename = __DIR__.'/../README.md';
$stdin = fopen($filename, 'r');

// This will count the number of words in the README.md file
$cmd = Command::factory("wc")
->option("--words")
->run($stdin);

fclose($stdin);

$words = trim($cmd->getStdOut());
echo "File $filename contains $words words\n";
```

Your system's `STDIN` is also a stream, so you can accept input that is typed on the command line or piped into your script as well:

```php
use kamermans\Command\Command;

echo "Type some words, one per line, then press CTRL-D and they will be sorted:\n";

$cmd = Command::factory("sort")
// This causes Command to use the real STDIN
->run(STDIN);

echo "\n";
echo $cmd->getStdOut();
```

Some more features:
- `StdIn` data can be provided to the process as a parameter to `run()`
Expand Down
14 changes: 14 additions & 0 deletions examples/stdin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

use kamermans\Command\Command;

require_once __DIR__.'/../vendor/autoload.php';

echo "Type some words, one per line, then press CTRL-D and they will be sorted:\n";

$cmd = Command::factory("sort")
// This causes Command to use the real STDIN
->run(STDIN);

echo "\n";
echo $cmd->getStdOut();
18 changes: 18 additions & 0 deletions examples/stdin_stream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use kamermans\Command\Command;

require_once __DIR__.'/../vendor/autoload.php';

$filename = __DIR__.'/../README.md';
$stdin = fopen($filename, 'r');

// This will count the number of words in the README.md file
$cmd = Command::factory("wc")
->option("--words")
->run($stdin);

fclose($stdin);

$words = trim($cmd->getStdOut());
echo "File $filename contains $words words\n";
12 changes: 12 additions & 0 deletions examples/stdin_string.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use kamermans\Command\Command;

require_once __DIR__.'/../vendor/autoload.php';

$stdin = "banana\norange\napple\npear\n";

$cmd = Command::factory("sort")
->run($stdin);

echo $cmd->getStdOut();
15 changes: 12 additions & 3 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public function argument($arg) {
/**
* Runs the command
*
* @param string $stdin
* @param string|resource $stdin The string contents for STDIN or a stream resource to be consumed
* @param bool $throw_exceptions If true (default), an exception will be thrown if the command fails
* @return Command - Fluent interface
*/
Expand Down Expand Up @@ -312,9 +312,18 @@ public static function exec($cmd, &$buffers, $callback = null, $callbacklines =
}

// Feed the process with the stdin if any and close it
if (!empty($buffers[self::STDIN])) {
fwrite($pipes[self::STDIN], $buffers[self::STDIN]);
$stdin = $buffers[self::STDIN];
if (is_resource($stdin)) {
// It seems this method is less memory-intensive that the stream copying builtin:
// stream_copy_to_stream(resource $source, resource $dest)
while(!feof($stdin)) {
fwrite($pipes[self::STDIN], fread($stdin, $readbuffer));
}

} else if (!empty($stdin)) {
fwrite($pipes[self::STDIN], $stdin);
}

fclose($pipes[self::STDIN]);

// Setup non-blocking behaviour for stdout and stderr
Expand Down

0 comments on commit 52443d7

Please sign in to comment.