guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Shell commands with output to string


From: post
Subject: Re: Shell commands with output to string
Date: Tue, 22 Feb 2022 11:43:13 +0100

Hi,

to throw in an example: I once used a function like the one below to handle stdout and stderr from external commands (from https://github.com/tdanckaert/jobview/blob/master/jobtools.scm#L38 ). Probably far from perfect (my first and only scheme project...), but hopefully it gives you an idea.

(define (process-output proc cmd)
  "Runs CMD as an external process, with an input port from which the
process' stdout may be read, and runs the procedure PROC that takes
this input port as a single argument.  Throws an exception 'cmd-failed
if CMD's exit status is non-zero."
  (let* ((err-pipe (pipe))
         (err-write (cdr err-pipe))
         (err-read (car err-pipe))
         (stderr (current-error-port)))
    (with-error-to-port err-write
      (lambda ()
        (let* ((port (open-input-pipe cmd))
               (ignore (setvbuf port 'block))
               (result
                (catch #t
                  ;; Catch any exception thrown by applying PROC to
                  ;; the output of CMD: if CMD fails, we check the
                  ;; exit status below; if CMD succeeds, PROC must be
                  ;; able to deal with its output.
                  (lambda () (proc port))
                  (lambda (key . args)
                    (format stderr "Caught exception ~a from ~y~%" key proc))))
               (status (close-pipe port)))
          (close-port err-write)
          (or (zero? status)
              (throw 'cmd-failed cmd status
                     (get-string-all err-read)))
          result)))))

Thomas


On 2022-02-22 11:20, Alex Sassmannshausen wrote:
Hi Zelphir,

I think you want to be using the popen / pipe procedures for this. See
https://www.gnu.org/software/guile/docs/docs-2.2/guile-ref/Pipes.html
for the chapter in the manual.

Hope this helps :)

Alex

Zelphir Kaltstahl <zelphirkaltstahl@posteo.de> writes:

Corrections below.

On 2/22/22 10:29, Zelphir Kaltstahl wrote:
Hello Guile users!

How would I run a shell command from inside Guile and get its output
as a string, instead of the output being outputted directly? (Guile
3.0.8)

So far I have found

~~~~
(system ...)
~~~~

which I tried to use with

~~~~
scheme@(guile-user)> (with-output-to-string
  (system "ls -al"))

;; lots of output immediately shown and not stored in variable

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Wrong type to apply: 0

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,bt
In ice-9/ports.scm:
    476:4  2 (with-output-to-string 0)
While executing meta-command:
In procedure frame-local-ref: Argument 2 out of range: 1
~~~~

But this does not give me a string back.

I also tried with

~~~~
scheme@(guile-user)> (call-with-values (lambda () (system "ls -al"))
... (lambda (exit-code output) output))

;; lots of output immediately shown

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Wrong number of values returned to continuation (expected 2)

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.

scheme@(guile-user) [1]> ,bt
In current input:
    10:29  1 (_)
In ice-9/boot-9.scm:
  1685:16  0 (raise-exception _ #:continuable? _)
~~~~

Is there another function I should be using?

I would like to have the exit code and the output of a command.

Best regards,
Zelphir

Of course I should use `with-output-to-string` correctly:

~~~~
scheme@(guile-user)> (with-output-to-string
  (lambda () (system "ls -al")))
;; directly outputted stuff
$1 = ""
~~~~

But still not a win.

Regards,
Zelphir



reply via email to

[Prev in Thread] Current Thread [Next in Thread]