#!/usr/bin/perl # # cpdir [options] d1 d2 # lndir [options] d1 d2 # # This does a recursive copy or link from d1 to d2, preserving links and times. # # Options: # +b Backup (using Cp and Rm) # +d Debug messages. # +m Merge (default: don't empty out target directories) # +n Newer files only. # +v Verbose messages (same as -d). # # By default, existing files under d2 will disappear whenever the # corresponding file under d1 is copied; existing files under d2 that don't # have a counterpart under d1 will be preserved. This is called "merging", # and can be defeated by the -m option, which will cause all existing files # under d2 to disappear. # $st = 0; $| = 1; ($op = $0) =~ s".*/""; $V = $ENV{"V_$op"} || $ENV{"D_$op"} || 1; $op =~ s/dir$//i; $op =~ s/-r$//i; $cp = 'cp'; $rm = 'rm'; $rd = 'rm -rf'; $merge = 1; # Merge directories by default. for $a (@ARGV) { if (($opf,$opt) = ($a =~ /^([-+])(.*)/)) { if ($opt =~ /b/i) { $backup = ($opf eq '+'); $cp = 'Cp'; $rm = 'Rm'; } if ($opt =~ /[dv]/i) { if ($opt =~ /[dv](\d+)/i) { $V = $1; } else { $V = 2; } } if ($opt =~ /m/i) { $merge = ($opf eq '+'); } if ($opt =~ /n/i) { $newer = ($opf eq '+'); } } else { if (!$d1) { $d1 = $a; } elsif (!$d2) { $d2 = $a; } else { printf STDERR "$0: Arg \"$a\" ignored.\n"; } } } die "Usage: $0 dir1 dir2\n" if (!d2); &cpdir($d1,$d2); exit $st; sub cpdir { local($d1,$d2) = @_; local(@files,$f,$p1,$p2,$x); local($dev1,$ino1,$md1,$nl1,$uid1,$gid1,$rd1,$sz1,$at1,$mt1); local($dev2,$ino2,$md2,$nl2,$uid2,$gid2,$rd2,$sz2,$at2,$mt2); if (!opendir(D,$d1)) { print STDERR "$0: Can't read \"$d1\" [$!]\n"; return 0; } system "$rm '$d2'" if (-f $d2 && $rm); system "$rd '$d2'" if (-d $d2 && $rd && !$merge); print "mkdir -p '$d2'\n" if ($V>1 && (!-d $d2)); system "mkdir -p '$d2'" if (! -d $d2); @files = readdir(D); for $f (@files) { next if $f eq '.'; next if $f eq '..'; $p1 = "$d1/$f"; $p2 = "$d2/$f"; if ($backup && -e $p2) { system "$rm '$f2'"; } ($dev1,$ino1,$md1,$nl1,$uid1,$gid1,$rd1,$sz1,$at1,$mt1) = stat($p1); ($dev2,$ino2,$md2,$nl2,$uid2,$gid2,$rd2,$sz2,$at2,$mt2) = stat($p2); if ($ino1 == $ino2 && $dev1 == $dev2) { print "== $p1\t$p2\n" if $V>2; next; } if (-d $p1) { &cpdir($p1,$p2); next; } if ($newer && (-f $p2) && ($mt1 <= $mt2)) { print "<< $p1\t$p2\n" if $V>1; next; } system "$rm '$p2'" if (-e $p2); if ($nl1 > 1) { if ($x = $ino{$dev1,$ino1}) { print "-> $x\t$p2\n" if $V>1; if (!link("$x","$p2")) { printf STDERR "$0: Can't link(\"$x\",\"$p2\") [$!]\n"; } } else { $ino{$dev1,$ino1} = $p2; print "$op '$p1' '$p2'\n" if $V>1; system "$op '$p1' '$p2'"; } } else { print "$op '$p1' '$p2'\n" if $V>1; system "$op '$p1' '$p2'"; } } }