Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] commands.getoutput () in ocaml?

14 views
Skip to first unread message

Luca de Alfaro

unread,
Aug 22, 2007, 3:59:33 PM8/22/07
to caml...@yquem.inria.fr
Dear All,

I am looking for a quick way to do the equivalent of

s = commands.getoutput ("ls " + name + "*")

in Ocaml.

Unix.system does perform a call, but the output of the call is not
returned... yes, I can redirect it to /tmp/output.ocaml and then read the
file, or even go crazy and build pipes, but is there a more elegant (read:
succint) way to do it?

Luca

malc

unread,
Aug 22, 2007, 4:07:49 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr

I needed something to that effect yesterday and wrote following:

open Unix;;

let getprocout cmd =
let ic = open_process_in cmd in
let b = Buffer.create 10 in
let rec loop () =
match try Some (input_line ic) with End_of_file -> None with
| None -> Buffer.contents b
| Some line ->
Buffer.add_string b line;
loop ()
in
loop ()
;;

--
vale

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

malc

unread,
Aug 22, 2007, 4:13:14 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr
On Thu, 23 Aug 2007, malc wrote:

> On Wed, 22 Aug 2007, Luca de Alfaro wrote:
>
>> Dear All,

[..snip..]

>
> open Unix;;
>
> let getprocout cmd =

[..snip..]
> ;;

This does not include closing of input channel and processing of
status. So Unix.close_process_in ought to be utilized somewhere.
Sorry about that.

Brian Hurt

unread,
Aug 22, 2007, 4:20:35 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr
Luca de Alfaro wrote:

If what you want is to spawn a process and redirect the I/O, the
standard library is short on convience functions- in this way Ocaml is
more similiar to C++/Java than it is Perl/Python/Ruby. Although the
convience functions are not that hard to write. If you want to read a
directory, you might want to look at Unix.opendir, Unix.readdir, etc.

Brian

Dave Benjamin

unread,
Aug 22, 2007, 4:41:20 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr
On Wed, 22 Aug 2007, Luca de Alfaro wrote:

> I am looking for a quick way to do the equivalent of
> s = commands.getoutput ("ls " + name + "*")
> in Ocaml.

I have translated many of the examples from the Perl Cookbook for the
Process Management and Communication chapter of the OCaml PLEAC. This is
one of the topics covered.

http://pleac.sourceforge.net/pleac_ocaml/processmanagementetc.html

Dave

Luca de Alfaro

unread,
Aug 22, 2007, 5:34:26 PM8/22/07
to Dave Benjamin, caml...@yquem.inria.fr
Thanks, this is truly wonderful!

I wish more of the things we are discussing and discovering in this email
list would make it to the official Ocaml site...

Luca

Yitzhak Mandelbaum

unread,
Aug 22, 2007, 6:14:24 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr
Perhaps its time for a stronger community process. A discussion about
this was started here a few weeks ago but it fizzled out pretty
quickly. It seems we need to find a balance between the best
interests of the ocaml developer community and the best interests of
ocaml compiler developers.

Is anybody familiar with the Java community process and how that
worked out?

Cheers,
Yitzhak

> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

--------------------------------------------------
Yitzhak Mandelbaum
AT&T Labs - Research

http://www.research.att.com/~yitzhak


Daniel Bünzli

unread,
Aug 22, 2007, 6:15:44 PM8/22/07
to Luca de Alfaro, caml...@yquem.inria.fr

Le 22 août 07 à 23:32, Luca de Alfaro a écrit :

> I wish more of the things we are discussing and discovering in this
> email list would make it to the official Ocaml site...

Feel free to add what you discover to this page :

http://cocan.org/faqs_and_programming_guidelines

Best,

Daniel

Olivier Andrieu

unread,
Aug 22, 2007, 6:38:10 PM8/22/07
to Dave Benjamin, caml...@yquem.inria.fr
On 8/22/07, Dave Benjamin <da...@ramenlabs.com> wrote:
> On Wed, 22 Aug 2007, Luca de Alfaro wrote:
>
> > I am looking for a quick way to do the equivalent of
> > s = commands.getoutput ("ls " + name + "*")
> > in Ocaml.
>
> I have translated many of the examples from the Perl Cookbook for the
> Process Management and Communication chapter of the OCaml PLEAC. This is
> one of the topics covered.
>
> http://pleac.sourceforge.net/pleac_ocaml/processmanagementetc.html

about this function:

(* Run a command and return its results as a string. *)
let read_process command =
let buffer_size = 2048 in
let buffer = Buffer.create buffer_size in
let string = String.create buffer_size in
let in_channel = Unix.open_process_in command in
let chars_read = ref 1 in
while !chars_read <> 0 do
chars_read := input in_channel string 0 buffer_size;
Buffer.add_string buffer (String.sub string 0 !chars_read)
done;
close_in in_channel;
Buffer.contents buffer

you could use Buffer.add_substring instead of add_string, that will
avoid an intermediate copy of the string

.. and you should be using Unix.close_process_in, not close_in
otherwise the subprocess will stay as a zombie.

--
Olivier

Eric Cooper

unread,
Aug 22, 2007, 7:07:38 PM8/22/07
to caml...@yquem.inria.fr
On Thu, Aug 23, 2007 at 12:35:14AM +0200, Olivier Andrieu wrote:
> you could use Buffer.add_substring instead of add_string, that will
> avoid an intermediate copy of the string

And you can use Buffer.add_channel to avoid intermediate strings
altogether (until the final Buffer.to_string).

--
Eric Cooper e c c @ c m u . e d u

Dave Benjamin

unread,
Aug 22, 2007, 7:29:33 PM8/22/07
to Eric Cooper, caml...@yquem.inria.fr
On Wed, 22 Aug 2007, Eric Cooper wrote:

> On Thu, Aug 23, 2007 at 12:35:14AM +0200, Olivier Andrieu wrote:
>> you could use Buffer.add_substring instead of add_string, that will
>> avoid an intermediate copy of the string
>
> And you can use Buffer.add_channel to avoid intermediate strings
> altogether (until the final Buffer.to_string).

Thanks, guys! I really appreciate the feedback, and will make these
suggested improvements (though it may take awhile to show up on the site).
If you find any other mistakes, please let me know.

Dave

Dave Benjamin

unread,
Aug 23, 2007, 12:36:33 AM8/23/07
to Eric Cooper, caml...@yquem.inria.fr
On Wed, 22 Aug 2007, Eric Cooper wrote:

> On Thu, Aug 23, 2007 at 12:35:14AM +0200, Olivier Andrieu wrote:
>> you could use Buffer.add_substring instead of add_string, that will
>> avoid an intermediate copy of the string
>
> And you can use Buffer.add_channel to avoid intermediate strings
> altogether (until the final Buffer.to_string).

I'm not quite sure how to do this, actually. Here's what I've got so far:

let read_process command =
let buffer_size = 2048 in
let buffer = Buffer.create buffer_size in

let in_channel = Unix.open_process_in command in

begin
try
while true do
Buffer.add_channel buffer in_channel buffer_size;
done
with
| End_of_file -> ()
| e ->
ignore (Unix.close_process_in in_channel);
raise e;
end;
ignore (Unix.close_process_in in_channel);
Buffer.contents buffer

However, this doesn't work unless I set buffer_size to 1. Otherwise, the
End_of_file fires before all the data is read in, so I either get nothing
or an incomplete result.

Any advice?

Thanks,
Dave

"Dr. Axel Poigné"

unread,
Aug 23, 2007, 11:31:50 AM8/23/07
to caml...@yquem.inria.fr
>
>
>> I am looking for a quick way to do the equivalent of
>> s = commands.getoutput ("ls " + name + "*")
>> in Ocaml.
>>
>
> I have translated many of the examples from the Perl Cookbook for
> the Process Management and Communication chapter of the OCaml
> PLEAC. This is one of the topics covered.
>
> http://pleac.sourceforge.net/pleac_ocaml/processmanagementetc.html
>
> Dave
>

There is a problem with the read_process_lines function though: if
the output buffer gets too long the process does not return to close
the input channel. Consequence is that the spawning process is blocked.

That's a problem I do not know how to solve.

Axel

Eric Cooper

unread,
Aug 23, 2007, 1:11:46 PM8/23/07
to caml...@yquem.inria.fr
On Wed, Aug 22, 2007 at 11:03:42PM -0500, Dave Benjamin wrote:
> However, this doesn't work unless I set buffer_size to 1. Otherwise, the
> End_of_file fires before all the data is read in, so I either get nothing
> or an incomplete result.

Since you can't use Pervasives.in_channel_length on a pipe, the only
way I see is to write a special add_channel_tail function, called only
when you catch the first Eof, that tries successively to add_channel
n, n-1, n-2, ... etc. bytes until it succeeds. Sigh.

--
Eric Cooper e c c @ c m u . e d u

_______________________________________________

0 new messages