[Top][All Lists]

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

Re: Shell commands with output to string

From: Zelphir Kaltstahl
Subject: Re: Shell commands with output to string
Date: Wed, 23 Feb 2022 01:26:44 +0000

Hi Oliver!

On 2/22/22 17:33, Olivier Dion wrote:
On Tue, 22 Feb 2022, Leo Butler <> wrote:
Olivier Dion via General Guile related discussions <>

On Tue, 22 Feb 2022, 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
I use the following:

(define-module (shell utils)
   #:use-module (ice-9 format)
   #:use-module (ice-9 popen)
   #:use-module (ice-9 textual-ports))

(define (shell% proc fmt . args)
   (let* ((port (open-input-pipe (format #f "~?" fmt args)))
          (output (proc port)))
     (close-pipe port)
You probably want to inspect the exit value of the shell process, so
that you can handle/throw the error. This is what I use (similar to your
You're absolutely right.  It would also probably a good idea to use
dynamic-wind for close-pipe in case an exception is thrown in
read-string I think.

(define* (shell-command-to-string cmd)
   (catch 'shell-command-error
     ;; thunk
     (lambda ()
       (let* ((port (open-pipe cmd OPEN_READ))
              (str (read-string port))
              (wtpd (close-pipe port))
              (xval (status:exit-val wtpd)))
         (if (or (eqv? xval #f) (> xval 0)) (throw 'shell-command-error cmd 
     ;; handler
     (lambda (key cmd str)
       (simple-format #t "ERROR: in command ~a\nstring: ~a\n" cmd str)
       (throw 'error-in-shell-command-to-string cmd str))))

(define-public (shell . args)
   (apply shell% (cons get-string-all args)))

(define-public (shell$ . args)
   (apply shell% (cons get-line args)))

(shell "ls" "-l")

The $ variant is to get a single line in the output.
I wonder why there is no module already in ice-9 which does this
stuff?  It seems like a lot of people are re-inventing the wheel.
There's ton of missing stuffs in the standard library IMO.  On top of my
head, filesystem paths manipulation (e.g. path-join) is also one that is
probably getting re-invented a lots.

I actually made something for that, trying to copy mostly the Python behavior for os.path.join:

Also available as a GNU Guix package, but not updated in a while on Guix. Repository contains more up to date version.

I believe that the successful story of Python is not just about its
pretty syntax, but also dues to its very large standard library.

I think so too. Although I sometimes have the feeling, that Guile does things in a cleaner way, once one figures out how to do them in the first place. One thing I really like are the ports. Stuff like call-with-output-string. Takes some twisting of the brain, but once one gets it, it becomes very useful and elegant.

But yes, Python is very beginner friendly in terms of batteries included. Although I think that its syntax feels a bit ad-hoc. As in "Oh we want some syntax for X … lets invent this keyword here." or some new operators or things like that. I like Guile syntax (or Scheme in general) much more. However, it is difficult to motivate others in a quick demo to learn the language, when you cannot take half an hour time to explain, what that for other people weird looking syntax is actually really cool.



reply via email to

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