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

Re: [Q] HOWTO redirect a i/o-port in Unix??



Quoting Leo Razoumov:
> More specifically, I am looking for a way to redirect stdout (and stderr) of a
> subprocess created with (process "myprog") into a file.

Quoting Matthias Felleisen:
> 
> Here is a (stupid) trick that I used in my Web page building scripts: 
> 
> (with-output-to-file "date.txt" 
>   (lambda () 
>     (display (read-line (car (process "date"))))))
> 
> This copies text from the process port to the file "date.txt". 

That works often. But sometimes the data coming from the process isn't
line-based, and often you want the data to get pushed from one port to
the other "in the background".

Here's a fairly general and efficient function:

 (define (copy-stream input-port output-port)
  (thread (lambda ()
            (let ([s (make-string 4096)])
              (let loop ()
                (let ([l (read-string! s input-port)])
                  (unless (eof-object? l)
                    (display (if (< l 4096) (substring s 0 l) s)
                             output-port)
                    (loop))))
              
              ;; For most contexts, it's good to
              ;; close the ports at this point:
              (close-input-port input-port)
              (close-output-port output-port)))))

Here's an example of its use:

 ;; Pipe "ls" output to "wc":
 (define ls-p (process "ls"))
 (define wc-p (process "wc"))

 (copy-stream (car ls-p)   ; car is stdout of ls
              (cadr wc-p)) ; cadr is stdin of wc-p
 (define t (copy-stream (car wc-p)
                        (current-output-port)))
 ;; wait until "wc" is done:
 (thread-wait t)


Matthew