#!/usr/bin/perl # # copy files using dd --symlynX 2011 # # I couldn't find anything like this on the Internet, either because # it is very hard to find suitable search words to find it, or maybe # because it is a really stupid idea to do this. # one meg seems to perform well, but YMMV my $bs = "bs=1048576"; # used by -r option only. my $t = "/dev/shm/.ddcp-$$"; use Getopt::Std; getopt('o'); # allow for both cp ( comes last) and -o syntax my $dest = $opt_o || pop; die <] [] [] Recursively copy directories containing large files using /bin/dd with a large block size. Sometimes dd will outperform regular file transfer tools like cp, cpio, rsync, tar. Sometimes even local loop HTTP achieves better performance than those. I have no idea why this happens to me. Maybe it doesn't to you, but if it does, you may find this useful. Usage just like "/bin/cp -rv". Options: -m move files (erase original after successful copy) -d try dd's dsync flag -s try dd's sync flag -r copy each file to RAM before writing to destination (a file called $t would be used) -o output directory, so you don't have to specify it at the end When no source files or directories are given, the current directory is used. Using none of the flags above has provided me with the best dd performance, even when copying between file systems on the same external USB drive. So the world isn't completely rotten after all. X system '/bin/mkdir', $dest unless -d $dest; # print "Dest: $dest\n"; # bs will be passed anyhow, but i can't pass a null string there my $f = $opt_s ? "oflag=sync" : $opt_d ? "oflag=dsync" : $bs; require "find.pl"; &find( @ARGV ? @ARGV : '.' ); exit; sub wanted { next if (-d $_); my $target = "$dest/$dir"; # print "Mkdir: $target\n"; system '/bin/mkdir', '-p', $target unless -d $target; # ($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_); print "\t$_\n"; if ($opt_r) { &system('/bin/dd', $bs, $f, "if=$_", "of=$t"); &system('/bin/dd', $bs, $f, "if=$t", "of=$target/$_"); unlink($t); } else { &system('/bin/dd', $bs, $f, "if=$_", "of=$target/$_"); } if ($opt_m and -s $_ eq -s "$target/$_") { unlink($_); } } sub system { if (system(@_)) { if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { printf "child exited with value %d\n", $? >> 8; } exit $?; } }