Merge branch 'vincent/rvalue_stmt_given' into blead
[p5sagit/p5-mst-13.2.git] / lib / File / Copy.pm
CommitLineData
f716a1dd 1# File/Copy.pm. Written in 1994 by Aaron Sherman <ajs@ajs.com>. This
2# source code has been placed in the public domain by the author.
3# Please be kind and preserve the documentation.
4#
71be2cbc 5# Additions copyright 1996 by Charles Bailey. Permission is granted
6# to distribute the revised code under the same terms as Perl itself.
f716a1dd 7
8package File::Copy;
9
3b825e41 10use 5.006;
71be2cbc 11use strict;
b395063c 12use warnings;
6c254d95 13use File::Spec;
96a91e01 14use Config;
e63b3379 15# During perl build, we need File::Copy but Scalar::Util might not be built yet
e55c0a82 16# And then we need these games to avoid loading overload, as that will
17# confuse miniperl during the bootstrap of perl.
18my $Scalar_Util_loaded = eval q{ require Scalar::Util; require overload; 1 };
17f410f9 19our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
20sub copy;
21sub syscopy;
22sub cp;
23sub mv;
71be2cbc 24
fff5c6e2 25$VERSION = '2.18';
f716a1dd 26
71be2cbc 27require Exporter;
28@ISA = qw(Exporter);
29@EXPORT = qw(copy move);
30@EXPORT_OK = qw(cp mv);
f716a1dd 31
441496b2 32$Too_Big = 1024 * 1024 * 2;
f716a1dd 33
8878f897 34sub croak {
35 require Carp;
36 goto &Carp::croak;
37}
38
754f2cd0 39sub carp {
40 require Carp;
41 goto &Carp::carp;
42}
43
bcdb689b 44my $macfiles;
45if ($^O eq 'MacOS') {
46 $macfiles = eval { require Mac::MoreFiles };
47 warn 'Mac::MoreFiles could not be loaded; using non-native syscopy'
3a2263fe 48 if $@ && $^W;
bcdb689b 49}
50
fc06fdeb 51# Look up the feature settings on VMS using VMS::Feature when available.
52
53my $use_vms_feature = 0;
54BEGIN {
55 if ($^O eq 'VMS') {
37930f0f 56 if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
fc06fdeb 57 $use_vms_feature = 1;
58 }
59 }
60}
61
62# Need to look up the UNIX report mode. This may become a dynamic mode
63# in the future.
64sub _vms_unix_rpt {
65 my $unix_rpt;
66 if ($use_vms_feature) {
67 $unix_rpt = VMS::Feature::current("filename_unix_report");
68 } else {
69 my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
70 $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
71 }
72 return $unix_rpt;
73}
74
75# Need to look up the EFS character set mode. This may become a dynamic
76# mode in the future.
77sub _vms_efs {
78 my $efs;
79 if ($use_vms_feature) {
80 $efs = VMS::Feature::current("efs_charset");
81 } else {
82 my $env_efs = $ENV{'DECC$EFS_CHARSET'} || '';
83 $efs = $env_efs =~ /^[ET1]/i;
84 }
85 return $efs;
86}
87
88
6c254d95 89sub _catname {
71be2cbc 90 my($from, $to) = @_;
91 if (not defined &basename) {
92 require File::Basename;
93 import File::Basename 'basename';
94 }
6c254d95 95
96 if ($^O eq 'MacOS') {
97 # a partial dir name that's valid only in the cwd (e.g. 'tmp')
98 $to = ':' . $to if $to !~ /:/;
99 }
100
101 return File::Spec->catfile($to, basename($from));
f716a1dd 102}
103
236a0738 104# _eq($from, $to) tells whether $from and $to are identical
236a0738 105sub _eq {
e55c0a82 106 my ($from, $to) = map {
107 $Scalar_Util_loaded && Scalar::Util::blessed($_)
108 && overload::Method($_, q{""})
109 ? "$_"
110 : $_
111 } (@_);
112 return '' if ( (ref $from) xor (ref $to) );
113 return $from == $to if ref $from;
114 return $from eq $to;
236a0738 115}
116
f716a1dd 117sub copy {
71be2cbc 118 croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ")
f716a1dd 119 unless(@_ == 2 || @_ == 3);
120
121 my $from = shift;
122 my $to = shift;
71be2cbc 123
671637fe 124 my $size;
125 if (@_) {
126 $size = shift(@_) + 0;
127 croak("Bad buffer size for copy: $size\n") unless ($size > 0);
128 }
129
71be2cbc 130 my $from_a_handle = (ref($from)
131 ? (ref($from) eq 'GLOB'
d704f39a 132 || UNIVERSAL::isa($from, 'GLOB')
133 || UNIVERSAL::isa($from, 'IO::Handle'))
71be2cbc 134 : (ref(\$from) eq 'GLOB'));
135 my $to_a_handle = (ref($to)
136 ? (ref($to) eq 'GLOB'
d704f39a 137 || UNIVERSAL::isa($to, 'GLOB')
138 || UNIVERSAL::isa($to, 'IO::Handle'))
71be2cbc 139 : (ref(\$to) eq 'GLOB'));
140
236a0738 141 if (_eq($from, $to)) { # works for references, too
754f2cd0 142 carp("'$from' and '$to' are identical (not copied)");
143 # The "copy" was a success as the source and destination contain
144 # the same data.
145 return 1;
96a91e01 146 }
147
ac7b122d 148 if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) &&
4c38808d 149 !($^O eq 'MSWin32' || $^O eq 'os2')) {
ac7b122d 150 my @fs = stat($from);
151 if (@fs) {
96a91e01 152 my @ts = stat($to);
16f708c9 153 if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1] && !-p $from) {
754f2cd0 154 carp("'$from' and '$to' are identical (not copied)");
155 return 0;
96a91e01 156 }
157 }
158 }
159
71be2cbc 160 if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) {
161 $to = _catname($from, $to);
162 }
163
1a04d035 164 if (defined &syscopy && !$Syscopy_is_copy
e6434134 165 && !$to_a_handle
1d84e8df 166 && !($from_a_handle && $^O eq 'os2' ) # OS/2 cannot handle handles
167 && !($from_a_handle && $^O eq 'mpeix') # and neither can MPE/iX.
7509b657 168 && !($from_a_handle && $^O eq 'MSWin32')
fa648be5 169 && !($from_a_handle && $^O eq 'MacOS')
2986a63f 170 && !($from_a_handle && $^O eq 'NetWare')
1a04d035 171 )
71be2cbc 172 {
4c38808d 173 my $copy_to = $to;
174
175 if ($^O eq 'VMS' && -e $from) {
176
177 if (! -d $to && ! -d $from) {
178
fc06fdeb 179 my $vms_efs = _vms_efs();
180 my $unix_rpt = _vms_unix_rpt();
181 my $unix_mode = 0;
182 my $from_unix = 0;
183 $from_unix = 1 if ($from =~ /^\.\.?$/);
184 my $from_vms = 0;
185 $from_vms = 1 if ($from =~ m#[\[<\]]#);
186
187 # Need to know if we are in Unix mode.
188 if ($from_vms == $from_unix) {
189 $unix_mode = $unix_rpt;
190 } else {
191 $unix_mode = $from_unix;
192 }
193
4c38808d 194 # VMS has sticky defaults on extensions, which means that
195 # if there is a null extension on the destination file, it
196 # will inherit the extension of the source file
197 # So add a '.' for a null extension.
198
fc06fdeb 199 # In unix_rpt mode, the trailing dot should not be added.
200
201 if ($vms_efs) {
202 $copy_to = $to;
203 } else {
204 $copy_to = VMS::Filespec::vmsify($to);
205 }
4c38808d 206 my ($vol, $dirs, $file) = File::Spec->splitpath($copy_to);
fc06fdeb 207 $file = $file . '.'
208 unless (($file =~ /(?<!\^)\./) || $unix_rpt);
4c38808d 209 $copy_to = File::Spec->catpath($vol, $dirs, $file);
210
211 # Get rid of the old versions to be like UNIX
212 1 while unlink $copy_to;
213 }
214 }
215
079cb8cc 216 return syscopy($from, $copy_to) || 0;
71be2cbc 217 }
218
219 my $closefrom = 0;
220 my $closeto = 0;
671637fe 221 my ($status, $r, $buf);
48a5c399 222 local($\) = '';
f716a1dd 223
23ba2776 224 my $from_h;
71be2cbc 225 if ($from_a_handle) {
23ba2776 226 $from_h = $from;
f716a1dd 227 } else {
cfa308ca 228 open $from_h, "<", $from or goto fail_open1;
23ba2776 229 binmode $from_h or die "($!,$^E)";
e63b3379 230 $closefrom = 1;
1a04d035 231 }
232
671637fe 233 # Seems most logical to do this here, in case future changes would want to
234 # make this croak for some reason.
235 unless (defined $size) {
236 $size = tied(*$from_h) ? 0 : -s $from_h || 0;
237 $size = 1024 if ($size < 512);
238 $size = $Too_Big if ($size > $Too_Big);
239 }
240
23ba2776 241 my $to_h;
71be2cbc 242 if ($to_a_handle) {
23ba2776 243 $to_h = $to;
1a04d035 244 } else {
fff5c6e2 245 $to_h = \do { local *FH }; # XXX is this line obsolete?
e63b3379 246 open $to_h, ">", $to or goto fail_open2;
91ca337e 247 binmode $to_h or die "($!,$^E)";
71be2cbc 248 $closeto = 1;
1a04d035 249 }
f716a1dd 250
71be2cbc 251 $! = 0;
252 for (;;) {
253 my ($r, $w, $t);
23ba2776 254 defined($r = sysread($from_h, $buf, $size))
71be2cbc 255 or goto fail_inner;
256 last unless $r;
257 for ($w = 0; $w < $r; $w += $t) {
23ba2776 258 $t = syswrite($to_h, $buf, $r - $w, $w)
71be2cbc 259 or goto fail_inner;
f716a1dd 260 }
261 }
71be2cbc 262
23ba2776 263 close($to_h) || goto fail_open2 if $closeto;
264 close($from_h) || goto fail_open1 if $closefrom;
71be2cbc 265
48a5c399 266 # Use this idiom to avoid uninitialized value warning.
f716a1dd 267 return 1;
1a04d035 268
f716a1dd 269 # All of these contortions try to preserve error messages...
270 fail_inner:
271 if ($closeto) {
272 $status = $!;
273 $! = 0;
23ba2776 274 close $to_h;
f716a1dd 275 $! = $status unless $!;
276 }
277 fail_open2:
278 if ($closefrom) {
279 $status = $!;
280 $! = 0;
23ba2776 281 close $from_h;
f716a1dd 282 $! = $status unless $!;
283 }
284 fail_open1:
f716a1dd 285 return 0;
286}
9b957b78 287
e63b3379 288sub cp {
71be2cbc 289 my($from,$to) = @_;
e63b3379 290 my(@fromstat) = stat $from;
291 my(@tostat) = stat $to;
292 my $perm;
293
294 return 0 unless copy(@_) and @fromstat;
295
296 if (@tostat) {
297 $perm = $tostat[2];
298 } else {
299 $perm = $fromstat[2] & ~(umask || 0);
300 @tostat = stat $to;
301 }
302 # Might be more robust to look for S_I* in Fcntl, but we're
303 # trying to avoid dependence on any XS-containing modules,
304 # since File::Copy is used during the Perl build.
305 $perm &= 07777;
306 if ($perm & 06000) {
307 croak("Unable to check setuid/setgid permissions for $to: $!")
308 unless @tostat;
309
310 if ($perm & 04000 and # setuid
311 $fromstat[4] != $tostat[4]) { # owner must match
312 $perm &= ~06000;
313 }
314
ed62bc33 315 if ($perm & 02000 && $> != 0) { # if not root, setgid
e63b3379 316 my $ok = $fromstat[5] == $tostat[5]; # group must match
317 if ($ok) { # and we must be in group
ed62bc33 318 $ok = grep { $_ == $fromstat[5] } split /\s+/, $)
e63b3379 319 }
320 $perm &= ~06000 unless $ok;
321 }
322 }
323 return 0 unless @tostat;
324 return 1 if $perm == ($tostat[2] & 07777);
325 return eval { chmod $perm, $to; } ? 1 : 0;
326}
327
328sub _move {
329 croak("Usage: move(FROM, TO) ") unless @_ == 3;
330
331 my($from,$to,$fallback) = @_;
754f2cd0 332
fa76202e 333 my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);
441496b2 334
71be2cbc 335 if (-d $to && ! -d $from) {
336 $to = _catname($from, $to);
337 }
338
339 ($tosz1,$tomt1) = (stat($to))[7,9];
340 $fromsz = -s $from;
e6434134 341 if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
342 # will not rename with overwrite
343 unlink $to;
344 }
4c38808d 345
346 my $rename_to = $to;
347 if (-$^O eq 'VMS' && -e $from) {
348
349 if (! -d $to && ! -d $from) {
fc06fdeb 350
351 my $vms_efs = _vms_efs();
352 my $unix_rpt = _vms_unix_rpt();
353 my $unix_mode = 0;
354 my $from_unix = 0;
355 $from_unix = 1 if ($from =~ /^\.\.?$/);
356 my $from_vms = 0;
357 $from_vms = 1 if ($from =~ m#[\[<\]]#);
358
359 # Need to know if we are in Unix mode.
360 if ($from_vms == $from_unix) {
361 $unix_mode = $unix_rpt;
362 } else {
363 $unix_mode = $from_unix;
364 }
365
4c38808d 366 # VMS has sticky defaults on extensions, which means that
367 # if there is a null extension on the destination file, it
368 # will inherit the extension of the source file
369 # So add a '.' for a null extension.
370
fc06fdeb 371 # In unix_rpt mode, the trailing dot should not be added.
372
373 if ($vms_efs) {
374 $rename_to = $to;
375 } else {
376 $rename_to = VMS::Filespec::vmsify($to);
377 }
4c38808d 378 my ($vol, $dirs, $file) = File::Spec->splitpath($rename_to);
fc06fdeb 379 $file = $file . '.'
380 unless (($file =~ /(?<!\^)\./) || $unix_rpt);
4c38808d 381 $rename_to = File::Spec->catpath($vol, $dirs, $file);
382
383 # Get rid of the old versions to be like UNIX
384 1 while unlink $rename_to;
385 }
386 }
387
388 return 1 if rename $from, $rename_to;
71be2cbc 389
71be2cbc 390 # Did rename return an error even though it succeeded, because $to
391 # is on a remote NFS file system, and NFS lost the server's ack?
392 return 1 if defined($fromsz) && !-e $from && # $from disappeared
393 (($tosz2,$tomt2) = (stat($to))[7,9]) && # $to's there
c9fbd0c8 394 ((!defined $tosz1) || # not before or
395 ($tosz1 != $tosz2 or $tomt1 != $tomt2)) && # was changed
71be2cbc 396 $tosz2 == $fromsz; # it's all there
1a04d035 397
71be2cbc 398 ($tosz1,$tomt1) = (stat($to))[7,9]; # just in case rename did something
762548ba 399
400 {
401 local $@;
402 eval {
754f2cd0 403 local $SIG{__DIE__};
e63b3379 404 $fallback->($from,$to) or die;
762548ba 405 my($atime, $mtime) = (stat($from))[8,9];
406 utime($atime, $mtime, $to);
407 unlink($from) or die;
408 };
409 return 1 unless $@;
410 }
fa76202e 411 ($sts,$ossts) = ($! + 0, $^E + 0);
1a04d035 412
71be2cbc 413 ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
414 unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
415 ($!,$^E) = ($sts,$ossts);
416 return 0;
441496b2 417}
9b957b78 418
e63b3379 419sub move { _move(@_,\&copy); }
420sub mv { _move(@_,\&cp); }
71be2cbc 421
9b957b78 422# &syscopy is an XSUB under OS/2
1d84e8df 423unless (defined &syscopy) {
424 if ($^O eq 'VMS') {
425 *syscopy = \&rmscopy;
426 } elsif ($^O eq 'mpeix') {
427 *syscopy = sub {
3f5ee302 428 return 0 unless @_ == 2;
1d84e8df 429 # Use the MPE cp program in order to
430 # preserve MPE file attributes.
431 return system('/bin/cp', '-f', $_[0], $_[1]) == 0;
432 };
cf2f24a4 433 } elsif ($^O eq 'MSWin32' && defined &DynaLoader::boot_DynaLoader) {
434 # Win32::CopyFile() fill only work if we can load Win32.xs
7509b657 435 *syscopy = sub {
436 return 0 unless @_ == 2;
437 return Win32::CopyFile(@_, 1);
438 };
bcdb689b 439 } elsif ($macfiles) {
fa648be5 440 *syscopy = sub {
441 my($from, $to) = @_;
442 my($dir, $toname);
443
444 return 0 unless -e $from;
445
446 if ($to =~ /(.*:)([^:]+):?$/) {
447 ($dir, $toname) = ($1, $2);
448 } else {
449 ($dir, $toname) = (":", $to);
450 }
451
452 unlink($to);
453 Mac::MoreFiles::FSpFileCopy($from, $dir, $toname, 1);
454 };
1d84e8df 455 } else {
1a04d035 456 $Syscopy_is_copy = 1;
1d84e8df 457 *syscopy = \&copy;
458 }
459}
f716a1dd 460
4611;
462
463__END__
a5f75d66 464
f716a1dd 465=head1 NAME
466
467File::Copy - Copy files or filehandles
468
a5f75d66 469=head1 SYNOPSIS
f716a1dd 470
5ce10329 471 use File::Copy;
f716a1dd 472
5ce10329 473 copy("file1","file2") or die "Copy failed: $!";
474 copy("Copy.pm",\*STDOUT);
441496b2 475 move("/dev1/fileA","/dev2/fileB");
f716a1dd 476
78e38bb6 477 use File::Copy "cp";
f716a1dd 478
23f3aea0 479 $n = FileHandle->new("/a/file","r");
c6dfe06b 480 cp($n,"x");
f716a1dd 481
482=head1 DESCRIPTION
483
441496b2 484The File::Copy module provides two basic functions, C<copy> and
485C<move>, which are useful for getting the contents of a file from
486one place to another.
487
488=over 4
489
0cdecedb 490=item copy
491X<copy> X<cp>
441496b2 492
493The C<copy> function takes two
f716a1dd 494parameters: a file to copy from and a file to copy to. Either
495argument may be a string, a FileHandle reference or a FileHandle
496glob. Obviously, if the first argument is a filehandle of some
497sort, it will be read from, and if it is a file I<name> it will
498be opened for reading. Likewise, the second argument will be
96a91e01 499written to (and created if need be). Trying to copy a file on top
500of itself is a fatal error.
71be2cbc 501
502B<Note that passing in
9b957b78 503files as handles instead of names may lead to loss of information
504on some operating systems; it is recommended that you use file
e6434134 505names whenever possible.> Files are opened in binary mode where
8dcee03e 506applicable. To get a consistent behaviour when copying from a
e6434134 507filehandle to a file, use C<binmode> on the filehandle.
f716a1dd 508
509An optional third parameter can be used to specify the buffer
510size used for copying. This is the number of bytes from the
3a964d77 511first file, that will be held in memory at any given time, before
f716a1dd 512being written to the second file. The default buffer size depends
338de517 513upon the file, but will generally be the whole file (up to 2MB), or
f716a1dd 5141k for filehandles that do not reference files (eg. sockets).
515
e63b3379 516You may use the syntax C<use File::Copy "cp"> to get at the C<cp>
517alias for this function. The syntax is I<exactly> the same. The
4efe685a 518behavior is nearly the same as well: as of version 2.15, <cp> will
e63b3379 519preserve the source file's permission bits like the shell utility
520C<cp(1)> would do, while C<copy> uses the default permissions for the
521target file (which may depend on the process' C<umask>, file
522ownership, inherited ACLs, etc.). If an error occurs in setting
523permissions, C<cp> will return 0, regardless of whether the file was
524successfully copied.
9c76cba2 525
0cdecedb 526=item move
527X<move> X<mv> X<rename>
441496b2 528
529The C<move> function also takes two parameters: the current name
71be2cbc 530and the intended name of the file to be moved. If the destination
531already exists and is a directory, and the source is not a
532directory, then the source file will be renamed into the directory
533specified by the destination.
534
535If possible, move() will simply rename the file. Otherwise, it copies
536the file to the new location and deletes the original. If an error occurs
537during this copy-and-delete process, you may be left with a (possibly partial)
441496b2 538copy of the file under the destination name.
539
e63b3379 540You may use the C<mv> alias for this function in the same way that
541you may use the <cp> alias for C<copy>.
441496b2 542
0cdecedb 543=item syscopy
544X<syscopy>
441496b2 545
9b957b78 546File::Copy also provides the C<syscopy> routine, which copies the
547file specified in the first parameter to the file specified in the
548second parameter, preserving OS-specific attributes and file
549structure. For Unix systems, this is equivalent to the simple
f1442e8b 550C<copy> routine, which doesn't preserve OS-specific attributes. For
551VMS systems, this calls the C<rmscopy> routine (see below). For OS/2
552systems, this calls the C<syscopy> XSUB directly. For Win32 systems,
553this calls C<Win32::CopyFile>.
9b957b78 554
bcdb689b 555On Mac OS (Classic), C<syscopy> calls C<Mac::MoreFiles::FSpFileCopy>,
556if available.
557
338de517 558B<Special behaviour if C<syscopy> is defined (OS/2, VMS and Win32)>:
9b957b78 559
71be2cbc 560If both arguments to C<copy> are not file handles,
561then C<copy> will perform a "system copy" of
9b957b78 562the input file to a new output file, in order to preserve file
563attributes, indexed file structure, I<etc.> The buffer size
71be2cbc 564parameter is ignored. If either argument to C<copy> is a
565handle to an opened file, then data is copied using Perl
9b957b78 566operators, and no effort is made to preserve file attributes
567or record structure.
568
55497cff 569The system copy routine may also be called directly under VMS and OS/2
570as C<File::Copy::syscopy> (or under VMS as C<File::Copy::rmscopy>, which
71be2cbc 571is the routine that does the actual work for syscopy).
9b957b78 572
573=item rmscopy($from,$to[,$date_flag])
0cdecedb 574X<rmscopy>
9b957b78 575
71be2cbc 576The first and second arguments may be strings, typeglobs, typeglob
577references, or objects inheriting from IO::Handle;
578they are used in all cases to obtain the
9b957b78 579I<filespec> of the input and output files, respectively. The
580name and type of the input file are used as defaults for the
581output file, if necessary.
582
583A new version of the output file is always created, which
584inherits the structure and RMS attributes of the input file,
585except for owner and protections (and possibly timestamps;
586see below). All data from the input file is copied to the
587output file; if either of the first two parameters to C<rmscopy>
588is a file handle, its position is unchanged. (Note that this
589means a file handle pointing to the output file will be
590associated with an old version of that file after C<rmscopy>
591returns, not the newly created version.)
592
593The third parameter is an integer flag, which tells C<rmscopy>
1fef88e7 594how to handle timestamps. If it is E<lt> 0, none of the input file's
595timestamps are propagated to the output file. If it is E<gt> 0, then
9b957b78 596it is interpreted as a bitmask: if bit 0 (the LSB) is set, then
597timestamps other than the revision date are propagated; if bit 1
598is set, the revision date is propagated. If the third parameter
599to C<rmscopy> is 0, then it behaves much like the DCL COPY command:
600if the name or type of the output file was explicitly specified,
601then no timestamps are propagated, but if they were taken implicitly
602from the input filespec, then all timestamps other than the
603revision date are propagated. If this parameter is not supplied,
604it defaults to 0.
605
606Like C<copy>, C<rmscopy> returns 1 on success. If an error occurs,
607it sets C<$!>, deletes the output file, and returns 0.
608
55497cff 609=back
610
f716a1dd 611=head1 RETURN
612
441496b2 613All functions return 1 on success, 0 on failure.
614$! will be set if an error was encountered.
f716a1dd 615
6c254d95 616=head1 NOTES
617
618=over 4
619
620=item *
621
622On Mac OS (Classic), the path separator is ':', not '/', and the
623current directory is denoted as ':', not '.'. You should be careful
624about specifying relative pathnames. While a full path always begins
625with a volume name, a relative pathname should always begin with a
626':'. If specifying a volume name only, a trailing ':' is required.
627
628E.g.
629
630 copy("file1", "tmp"); # creates the file 'tmp' in the current directory
631 copy("file1", ":tmp:"); # creates :tmp:file1
632 copy("file1", ":tmp"); # same as above
0cdecedb 633 copy("file1", "tmp"); # same as above, if 'tmp' is a directory (but don't do
6c254d95 634 # that, since it may cause confusion, see example #1)
635 copy("file1", "tmp:file1"); # error, since 'tmp:' is not a volume
636 copy("file1", ":tmp:file1"); # ok, partial path
637 copy("file1", "DataHD:"); # creates DataHD:file1
0cdecedb 638
907fbfa1 639 move("MacintoshHD:fileA", "DataHD:fileB"); # moves (doesn't copy) files from one
6c254d95 640 # volume to another
641
642=back
643
f716a1dd 644=head1 AUTHOR
645
441496b2 646File::Copy was written by Aaron Sherman I<E<lt>ajs@ajs.comE<gt>> in 1995,
bd3fa61c 647and updated by Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>> in 1996.
f716a1dd 648
649=cut
441496b2 650