From: Jason Kantz
Subject: how to copy files?
Date: 
Message-ID: <3828630B.7D91607@yahoo.com>
How can I copy files in CL?
I found rename-file ... but no copy.
I'd like to avoid run-shell-command if possible.

--
Jason Kantz
http://www.iserv.net/~jfosterk

From: Barry Margolin
Subject: Re: how to copy files?
Date: 
Message-ID: <xwZV3.24$vE2.560@burlma1-snr2>
In article <················@yahoo.com>,
Jason Kantz  <········@yahoo.com> wrote:
>How can I copy files in CL?
>I found rename-file ... but no copy.
>I'd like to avoid run-shell-command if possible.

(defun copy-file (source dest)
(with-open-file (input source :direction :input)
  (with-open-file (output dest :direction :output)
    (loop for char = (read-char input)
          while char
      do (write-char char output))))

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Pekka P. Pirinen
Subject: Re: how to copy files?
Date: 
Message-ID: <ixogd24cz1.fsf@gaspode.cam.harlequin.co.uk>
Barry Margolin <······@bbnplanet.com> writes:
> >How can I copy files in CL? [...]
> >I'd like to avoid run-shell-command if possible.
> 
> (defun copy-file (source dest)
>   (with-open-file (input source :direction :input)
>     (with-open-file (output dest :direction :output)
>       (loop for char = (read-char input)
>             while char
>         do (write-char char output))))

Only if you know that the input files will all have the default
format, otherwise you need to take a bit of care that the output file
has the same one:

(defun copy-file (source dest)
  (with-open-file (input source :direction :input)
    (with-open-file (output dest :direction :output
                            :element-type (stream-element-type input)
                            :external-format (stream-external-format input))
      (loop for char = (read-char input)
            while char
        do (write-char char output))))

Line terminator translation and variations in the use of escape
sequences of multibyte encondings might still cause differences.  If
you need a byte-by-byte identical copy, you must do it with a byte
stream (READ-BYTE).

You'll probably want some :IF-EXISTS argument in there as well.

Also, as I'm sure you know, it's not very efficient to do it a
character at a time.  Using READ-LINE or READ-SEQUENCE gets more
complicated, though, and the principle is the same.  Even so, it might
a better use of the programmer's time to use an
implementation-provided routine (many have them), an OS call (where it
exists), or even RUN-SHELL-COMMAND.
-- 
Pekka P. Pirinen
Adaptive Memory Management Group, Harlequin Limited
Mail should be private, whether on paper or on disk.  Public gatherings
should be a right, whether virtual or in person.
From: Robert Monfera
Subject: Re: how to copy files?
Date: 
Message-ID: <38299F40.DB11A33E@fisec.com>
A few months ago (less than a year ago I think) there was a thread on
efficient file copying.  It evolved on the newsgroup, and performed
byte-based I/O in disk-sized blocks.  It was about twice as fast as
copying the file with Windows 98.  If speed is important, look it up
with http://www.deja.com (power search).

Robert

Jason Kantz wrote:
> 
> How can I copy files in CL?
> I found rename-file ... but no copy.
> I'd like to avoid run-shell-command if possible.
> 
> --
> Jason Kantz
> http://www.iserv.net/~jfosterk
From: Jason Kantz
Subject: Re: how to copy files?
Date: 
Message-ID: <3829761B.C863BBAC@yahoo.com>
Is there much difference between 

(defun copy-file (from to)
  (with-open-file (input from :direction :input)
    (with-open-file (output to :direction :output)
      (loop for char = (read-char input nil 'eof)
          until (equal char 'eof)
	  do (write-char char output)))))

and ...

(defun copy-file (from to)
    (with-open-file (in from :direction :input)
      (with-open-file (out to :direction :output)
        (let ((tmp (make-array 4096 :element-type 'base-char)))
          (loop for bytes = (read-sequence tmp in) until (zerop bytes)
            do (write-sequence tmp out :end bytes))))))

Jason Kantz wrote:
> 
> How can I copy files in CL?
> I found rename-file ... but no copy.
> I'd like to avoid run-shell-command if possible.
> 
> --
> Jason Kantz
> http://www.iserv.net/~jfosterk

-- 
==
Jason Kantz
http://www.iserv.net/~jfosterk
From: Robert Pluim
Subject: Re: how to copy files?
Date: 
Message-ID: <m3g0yetpd0.fsf@lem1.corpemea.baynetworks.com>
Jason Kantz <········@yahoo.com> writes:

> Is there much difference between 
> 
> (defun copy-file (from to)
>   (with-open-file (input from :direction :input)
>     (with-open-file (output to :direction :output)
>       (loop for char = (read-char input nil 'eof)
>           until (equal char 'eof)
> 	  do (write-char char output)))))
> 
> and ...
> 
> (defun copy-file (from to)
>     (with-open-file (in from :direction :input)
>       (with-open-file (out to :direction :output)
>         (let ((tmp (make-array 4096 :element-type 'base-char)))
>           (loop for bytes = (read-sequence tmp in) until (zerop bytes)
>             do (write-sequence tmp out :end bytes))))))

You mean apart from the fact that the second is way faster (on my
system using clisp, anyway. YMMV :-)

Robert
-- 
The above are my opinions,
 and my opinions only.
From: Rainer Joswig
Subject: Re: how to copy files?
Date: 
Message-ID: <joswig-1011991544360001@mac-rjo.work.maz.net>
In article <··············@lem1.corpemea.baynetworks.com>, Robert Pluim <······@bigfoot.com> wrote:

> Jason Kantz <········@yahoo.com> writes:
> 
> > Is there much difference between 
> > 
> > (defun copy-file (from to)
> >   (with-open-file (input from :direction :input)
> >     (with-open-file (output to :direction :output)
> >       (loop for char = (read-char input nil 'eof)
> >           until (equal char 'eof)
> >         do (write-char char output)))))
> > 
> > and ...
> > 
> > (defun copy-file (from to)
> >     (with-open-file (in from :direction :input)
> >       (with-open-file (out to :direction :output)
> >         (let ((tmp (make-array 4096 :element-type 'base-char)))
> >           (loop for bytes = (read-sequence tmp in) until (zerop bytes)
> >             do (write-sequence tmp out :end bytes))))))
> 
> You mean apart from the fact that the second is way faster (on my
> system using clisp, anyway. YMMV :-)

For more hairy code see HTTP:COPY-FILE in CL-HTTP.

Rainer Joswig, ISION Internet AG, Harburger Schlossstra�e 1, 
21079 Hamburg, Germany, Tel: +49 40 77175 226
Email: ·············@ision.de , WWW: http://www.ision.de/
From: Robert Monfera
Subject: Re: how to copy files?
Date: 
Message-ID: <3829A415.B80CDAD2@fisec.com>
Rainer Joswig wrote:

> For more hairy code see HTTP:COPY-FILE in CL-HTTP.

It is probably faster and platform-independent, but someone here
complained it's quite slow (taking multiple times long) in comparison to
OS-level copying.  It may have changed though.

Robert
From: Barry Margolin
Subject: Re: how to copy files?
Date: 
Message-ID: <LqiW3.65$vE2.2279@burlma1-snr2>
In article <·················@fisec.com>,
Robert Monfera  <·······@fisec.com> wrote:
>Rainer Joswig wrote:
>
>> For more hairy code see HTTP:COPY-FILE in CL-HTTP.
>
>It is probably faster and platform-independent, but someone here
>complained it's quite slow (taking multiple times long) in comparison to
>OS-level copying.  It may have changed though.

OS-level copying typically takes advantage of OS-specific features such as
memory mapping.  A common implementation of the cp command on Unix does
something like:

  source_desc = open(sourcefile, O_RDONLY);
  fstat(source_des, &statbuf)
  src_ptr = mmap(null, statbuf.st_size, PROT_READ, MAP_SHARED, source_desc, 0);
  dest_desc = open(destfile, O_WRONLY);
  write(dest_desc, src_ptr, statbuf.st_size);

Whoosh! the file is copied in one fell swoop by that last call, rather than
having to perform a system call for each block of the file.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Robert Monfera
Subject: Re: how to copy files?
Date: 
Message-ID: <3829B7E3.78AB8241@fisec.com>
Barry Margolin wrote:

> OS-level copying typically takes advantage of OS-specific features
> such as memory mapping.

Yes, I would have thought so - that's why I was surprised to learn that
the optimized Lisp copying (that was published was actually _faster_
than copying a file in windows 98 (if you consider it an OS).

Robert
From: Rainer Joswig
Subject: Re: how to copy files?
Date: 
Message-ID: <joswig-1011991904260001@mac-rjo.work.maz.net>
In article <·················@fisec.com>, ·······@fisec.com wrote:

> Rainer Joswig wrote:
> 
> > For more hairy code see HTTP:COPY-FILE in CL-HTTP.
> 
> It is probably faster and platform-independent, but someone here
> complained it's quite slow (taking multiple times long) in comparison to
> OS-level copying.  It may have changed though.

No, platforms should have platform dependent versions of it.
MCL has for example versions using file system buffers:

(defun io-buffer-write-file (io-buffer pathname &optional (start 0) end)
   (with-fsopen-file (pb pathname)
       (let* ((write-buf (io-buffer-outbuf io-buffer))
                 (filesize (the integer (geteof pb))))
          ;; check for bad arguments
          (when (or (< start 0) (>= start filesize))
              (error "Start index of ~s is not between 0 & ~s" start filesize))
          (if end
             (when (or (< end start) (> end filesize))      ; fixed -- JCMa 7/25/1997. RJ
                 (error "End index of ~s is not between ~s and ~s" end start filesize))
             (setq end filesize))
          (setfpos pb start)        ;set file position
          (with-io-buffer-locked (io-buffer)
              (%io-buffer-force-output io-buffer nil)         ; ensure that the buffer is empty
              (let ((bytes-left (- end start)))
                 (loop
                    (when (<= bytes-left 0) (return))
                    (let ((bytes (min (io-buffer-outcount io-buffer) bytes-left)))
                       (fsread pb bytes write-buf)
                       (decf bytes-left bytes)
                       (decf (io-buffer-outcount io-buffer) bytes)
                       (incf (io-buffer-bytes-written io-buffer) bytes)
                       (%setf-macptr (io-buffer-outptr io-buffer) (%inc-ptr write-buf bytes))
                       (%io-buffer-force-output io-buffer nil))))))))

Rainer Joswig, ISION Internet AG, Harburger Schlossstra�e 1, 
21079 Hamburg, Germany, Tel: +49 40 77175 226
Email: ·············@ision.de , WWW: http://www.ision.de/