movefile and copyfile

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

movefile and copyfile

John W. Eaton-6
How should the movefile and copyfile functions be implemented?  I was
hoping to be able to implement them in .m files, though it might not
be as simple as I was thinking.  I don't think there is any system
call or library function specified by POSIX to copy a file.  For
moving files, there is rename (and Octave already has a wrapper for
it) but that doesn't seem to be enough to do the job.  For example, I
thought the following would be sufficient:

  ## -*- texinfo -*-
  ## @deftypefn {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@var{f1}, @var{f2}})
  ## Move the file @var{f1} to the new name @var{f2}.  The name @var{f1}
  ## may contain globbing patterns.  If @var{f1} expands to multiple file
  ## names, @var{f2} must be a directory.
  ##
  ## If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\
  ## character strings.  Otherwise, @var{status} is 0, @var{msg} contains a\n\
  ## system-dependent error message, and @var{msgid} contains a unique\n\
  ## message identifier.\n\
  ## @seealso{glob}
  ## @end deftypefn

  function [status, msg, msgid] = movefile (f1, f2)

    status = true;
    msg = "";
    msgid = "movefile";

    if (nargin == 2)
      flist = glob (f1);
      nfiles = numel (flist);
      if (nfiles > 1)
        [f2info, err, msg] = stat (f2);
        if (err < 0)
          status = false;
        else
          if (S_ISDIR (f2info.mode))
            for i = 1:nfiles
              [err, msg] = rename (flist{i}, f2);
              if (err < 0)
                status = false;
                break;
              endif
            endfor
          else
            status = false;
            msg = "when moving multiple files, destination must be a directory";
          endif
        endif
      else
        [err, msg] = rename (f1, f2);
        if (err < 0)
          status = false;
          break;
        endif
      endif
    else
      usage ("movefile (f1, f2)");
    endif

    if (status)
      msgid = "";
    endif

  endfunction

but this fails if you try to move a file across devices.

My next thought was that we could maybe extract the code from the GNU
coreutils, but that is maybe not so trivial since the code is not
really designed to be used as a library.  Adapting the bits we need
into Octave means we have to maintain a forked version of the code.

I would rather not attempt something like

  system (sprintf ("mv %s %s"), f1, f2);

since that is not portable.

Suggestions or comments?

jwe