#!/usr/local/bin/perl # # $Id: pmvmac,v 0.70 2005/08/09 15:47:00 dankogai Exp $ # use strict; use Getopt::Std; use File::stat; use File::Basename; my %Opt; getopts("fivD", \%Opt); $Opt{i} and delete $Opt{f}; # for safety my $IAM = basename($0); my %Hardlink; # key = inode, val = name of first file copied my $Dst = pop @ARGV; @ARGV or help(); my $Dstst = stat($Dst); # not lstat; symlink to directory allowed unless (-d _){ @ARGV == 1 or help(); do_move($ARGV[0], $Dst); }else{ $Dst =~ s,/+$,,o; for my $src (@ARGV){ $src =~ s,/+$,,o; do_move($src, $Dst . '/' . basename($src)); } } exit; use MacOSX::File::Copy; use MacOSX::File::Catalog; use File::Path; sub do_move{ my ($src, $dst) = @_; $Opt{v} and print STDERR "$src\n"; # clean up destination if (my $dstst = lstat($dst)){ $Opt{i} and prompt($dst) or return; rmtree([ $dst ]) or "warn; can't rmtree $dst" and return; } if ( lstat($src)->dev == $Dstst->dev ){ $Opt{D} and warn "intra-device move"; return move($src, $dst); }else{ $Opt{D} and warn "cross-device move"; my @cmd = $Opt{D} ? qw(perl -Mblib bin/pcpmac) : 'pcpmac'; my $err = system(@cmd, '-pr', $src, $dst); $err == 0 and rmtree([ $src ]); $! and warn $!; } } sub prompt{ my $path = shift; $| = 1; print "Overwrite $path? [y/N]:"; my $answer = ; chomp $answer; return lc($answer) eq 'y'; } sub help{ warn caller; print STDERR <<"EOT"; usage: $IAM [-f|-i] src target $IAM [-f|-i] src1 ... srcN directory EOT exit; } 1; __END__ =head1 NAME pmvmac -- MvMac(1), or mv(1), implemented as perl script =head1 SYNOPSIS pmvmac [-f|-i] source_file target_file pmvmac [-f|-i] source_file ... target_directory =head1 TIGER As of Mac OS X v10.4 (Tiger), the ordinary L does support resource fork. =head1 DESCRIPTION pmvmac, as its name implies, moves files with finder info and resource fork. In the first synopsis form, pmvmac renames the source_file to the target_file. In the second synopsis form, each named source_file is moved to the destination target_directory. The names of the files themselves are not changed. If mv detects an attempt to move a file to itself, the copy will fail. The following options are available: =item -f Foreach existing destination pathname, attempt to overwrite it. If permissions do not allow move to succeed, remove it without prompting for confirmation. =item -i Causes pmvmac to write a prompt to the standard error output before copying a file that would overwrite an existing file. If the response from the standard input begins with the character "y" or "Y", the file move is attempted. For safety, this option cancels -f option. This is the opposite of BSD mv implementation. =item -v Verbose mode. Prints each items copied to standard output. =head2 Cross-volume move When mvmac tries to move items accross volumes, pmvmac uses pcpmac and File::Path::rmtree() to accomplish the move. The effect is equivalent to: rm -f destination_path && \ pcpmac -r source_file destination && \ rm -rf source_file =head1 AUTHOR Dan Kogai =head1 SEE ALSO L L =head1 COPYRIGHT Copyright 2002-2005 Dan Kogai This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.