Skip to content

Commit 52443d7

Browse files
committed
Improved STDIN support, added examples
1 parent 5ddaf43 commit 52443d7

File tree

5 files changed

+109
-3
lines changed

5 files changed

+109
-3
lines changed

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,59 @@ $cmd = Command::factory('grep CRON < /var/log/syslog | head', true)
9292
->run();
9393
```
9494

95+
## Using STDIN
96+
You can provide data for STDIN using a string or a stream resource (like a file handle)
97+
98+
### STDIN from a String
99+
100+
```php
101+
use kamermans\Command\Command;
102+
103+
$stdin = "banana
104+
orange
105+
apple
106+
pear
107+
";
108+
109+
$cmd = Command::factory("sort")
110+
->run($stdin);
111+
112+
echo $cmd->getStdOut();
113+
```
114+
115+
### STDIN from a Stream
116+
117+
```php
118+
use kamermans\Command\Command;
119+
120+
$filename = __DIR__.'/../README.md';
121+
$stdin = fopen($filename, 'r');
122+
123+
// This will count the number of words in the README.md file
124+
$cmd = Command::factory("wc")
125+
->option("--words")
126+
->run($stdin);
127+
128+
fclose($stdin);
129+
130+
$words = trim($cmd->getStdOut());
131+
echo "File $filename contains $words words\n";
132+
```
133+
134+
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:
135+
136+
```php
137+
use kamermans\Command\Command;
138+
139+
echo "Type some words, one per line, then press CTRL-D and they will be sorted:\n";
140+
141+
$cmd = Command::factory("sort")
142+
// This causes Command to use the real STDIN
143+
->run(STDIN);
144+
145+
echo "\n";
146+
echo $cmd->getStdOut();
147+
```
95148

96149
Some more features:
97150
- `StdIn` data can be provided to the process as a parameter to `run()`

examples/stdin.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
use kamermans\Command\Command;
4+
5+
require_once __DIR__.'/../vendor/autoload.php';
6+
7+
echo "Type some words, one per line, then press CTRL-D and they will be sorted:\n";
8+
9+
$cmd = Command::factory("sort")
10+
// This causes Command to use the real STDIN
11+
->run(STDIN);
12+
13+
echo "\n";
14+
echo $cmd->getStdOut();

examples/stdin_stream.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
use kamermans\Command\Command;
4+
5+
require_once __DIR__.'/../vendor/autoload.php';
6+
7+
$filename = __DIR__.'/../README.md';
8+
$stdin = fopen($filename, 'r');
9+
10+
// This will count the number of words in the README.md file
11+
$cmd = Command::factory("wc")
12+
->option("--words")
13+
->run($stdin);
14+
15+
fclose($stdin);
16+
17+
$words = trim($cmd->getStdOut());
18+
echo "File $filename contains $words words\n";

examples/stdin_string.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use kamermans\Command\Command;
4+
5+
require_once __DIR__.'/../vendor/autoload.php';
6+
7+
$stdin = "banana\norange\napple\npear\n";
8+
9+
$cmd = Command::factory("sort")
10+
->run($stdin);
11+
12+
echo $cmd->getStdOut();

src/Command.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function argument($arg) {
185185
/**
186186
* Runs the command
187187
*
188-
* @param string $stdin
188+
* @param string|resource $stdin The string contents for STDIN or a stream resource to be consumed
189189
* @param bool $throw_exceptions If true (default), an exception will be thrown if the command fails
190190
* @return Command - Fluent interface
191191
*/
@@ -312,9 +312,18 @@ public static function exec($cmd, &$buffers, $callback = null, $callbacklines =
312312
}
313313

314314
// Feed the process with the stdin if any and close it
315-
if (!empty($buffers[self::STDIN])) {
316-
fwrite($pipes[self::STDIN], $buffers[self::STDIN]);
315+
$stdin = $buffers[self::STDIN];
316+
if (is_resource($stdin)) {
317+
// It seems this method is less memory-intensive that the stream copying builtin:
318+
// stream_copy_to_stream(resource $source, resource $dest)
319+
while(!feof($stdin)) {
320+
fwrite($pipes[self::STDIN], fread($stdin, $readbuffer));
321+
}
322+
323+
} else if (!empty($stdin)) {
324+
fwrite($pipes[self::STDIN], $stdin);
317325
}
326+
318327
fclose($pipes[self::STDIN]);
319328

320329
// Setup non-blocking behaviour for stdout and stderr

0 commit comments

Comments
 (0)