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
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.
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.
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
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
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.
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/
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
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.
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
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/