Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Utility to calculate best way to archive Dir to DVD

by slugman (Novice)
on Aug 02, 2013 at 14:19 UTC ( [id://1047606]=CUFP: print w/replies, xml ) Need Help??

So, I made a utility to help me backup some data I found on my old hard drive. I hadn't seen this stuff in 10 years, and since I've lost backups along the way I didn't want to pass up the opportunity to backup my precious data. Also, since this drive is only 40G, its feasible to backup to 8 or 9 DVDs.

So basically, you launch the script, and tell it in order:

ARGV0 - directory to perform calculations on. ARGV1 - Size to output data, KB or MB. ARGV2 - wether you want size stats on directories or just output. ARGV3 - A single directory to skip or several directories. Several directories must be comma seperated with no spaces in between.

Features I would like to add: a pod style help document which explains how to use this. Also, I would like to be able to dynamically switch between the arguments, so they don't have to be in a particular order (thats how most *nix utilities work, with a few exceptions like mount and stuff.. right?).

#!/usr/bin/perl # # # # DVD_DIR_SUM # # This script will find the size of all the directories in # the given master directory, and provide the appropriate # directories which will fit inside a sandard DVD. # Diego Z Pineda # dzpineda86@gmail.com # July 22, 2013 use strict; use warnings; sub nl () { print "\n"; print "\n" } my $in_dir = $ARGV[0]; my $units = $ARGV[1]; my $skip = $ARGV[3]; my $skpdr = "$in_dir/$skip"; my @sks; if ($units !~ m{(K|M)B}i ) { print 'Please use appropriate units KB or MB for 2nd argument.'; nl; exit } my $dvd_s; if ($units =~ m{KB}) { $dvd_s = 4699999 } elsif ($units =~ m{MB}) { $dvd_s = 4699 } my @num = qx[du -B $units -d 1 $in_dir | cut -f 1]; my @dir = qx[du -B $units -d 1 $in_dir | cut -f 2]; my @dig; my @vdr; my $sum = 0; my $pre_elm; my $ni = $#num; my $in = $ni + 1; my $si; if ($skip =~ m{,}) { @sks = split(',', "$skip"); $si = $#sks + 1; for (my $i = 0; $i < $in; $i++) { for (my $j = 0; $j < $si; $j++) { if ($dir[$i] =~ m{$sks[$j]}) { $num[$i] = 0 }}}} elsif ($skip !~ m{,}) { for (my $i = 0; $i < $in; $i++) { if ($dir[$i] =~ m{$skip}) { $num[$i] = 0 }}} else { print "$skip is not a directory. Please ensure $skip is a dir i +nside $in_dir." } my $str1 = 'Last directory to load is:'; my $str2 = 'Total DVD size is:'; my $str3 = 'Root directory is:'; my $str4 = 'Skipped the following directories'; pop @num; pop @dir; nl; for (my $i = 0; $i < $in; $i++ ) { my $temp = $num[$i]; if ($units =~ m{KB}) { $units =~ s{KB}{kB}g } $temp =~ s{$units}{}g; $temp =~ s{ $}{}g; chomp $temp; push @dig, $temp } for (my $i = 0; $i < $in; $i++ ) { my $temp = $dir[$i]; $temp =~ s{$in_dir/}{}g; chomp $temp; push @vdr, $temp } for (my $i = 0; $i < $in; $i++) { if ($sum < $dvd_s) { $sum = $sum + $dig[$i]; $pre_elm = $i }} my $tru_sum = $sum - $dig[$pre_elm]; my $tru_elm = $pre_elm - 1; my $tru_dir = $vdr[$tru_elm]; if ($ARGV[2] =~ m{yes|y}i) { print "$str3\t$in_dir"; nl; for (my $i=0; $i < $tru_elm; $i++) { print "$dig[$i] $units\t\t$vdr[$i]"; nl }} print "$str1\t$tru_dir"; nl; print "$str2\t$tru_sum $units"; nl; if ($skip !~ "" && $skip !~ m{,}) { print "$str4:\t\t$skip"; nl } elsif ($si > 0) { print "$str4:"; for (my $i = 0; $i < $si; $i++) { my $i2 = $i + 1; nl; print "$i2\t\t$sks[$i]" }}

Replies are listed 'Best First'.
Re: Utility to calculate best way to archive Dir to DVD
by toolic (Bishop) on Aug 02, 2013 at 15:30 UTC
    Features I would like to add: a pod style help document which explains how to use this. Also, I would like to be able to dynamically switch between the arguments,
    This should give you a kickstart: Documentation and help texts
Re: Utility to calculate best way to archive Dir to DVD
by jwkrahn (Abbot) on Aug 03, 2013 at 11:44 UTC
    sub nl () { print "\n"; print "\n" }

    Why print twice and not just:

    sub nl () { print "\n\n" }



    if ($units !~ m{(K|M)B}i ) {

    For single characters you should use a character class, especially when you don't need capturing parentheses:

    if ($units !~ /[KM]B/i ) {



    my @num = qx[du -B $units -d 1 $in_dir | cut -f 1]; my @dir = qx[du -B $units -d 1 $in_dir | cut -f 2];

    my version of du doesn't have the -d switch so I couldn't test this.




    if ($skip =~ m{,}) { @sks = split(',', "$skip"); $si = $#sks + 1; for (my $i = 0; $i < $in; $i++) { for (my $j = 0; $j < $si; $j++) { if ($dir[$i] =~ m{$sks[$j]}) { $num[$i] = 0 }}}} elsif ($skip !~ m{,}) { for (my $i = 0; $i < $in; $i++) { if ($dir[$i] =~ m{$skip}) { $num[$i] = 0 }}} else { print "$skip is not a directory. Please ensure $skip is a dir i +nside $in_dir." }

    The test for a comma is unnecessary because split will work correctly with or without the comma.    And you don't test the value of $skip so you don't know whether it is a directory or not so the print line makes no sense.

    my @sks = split /,/, $skip; for my $i ( 0 .. $#num ) { for my $j ( 0 .. $#sks ) { if ( $dir[ $i ] =~ /$sks[$j]/ ) { $num[ $i ] = 0; } } }



    for (my $i = 0; $i < $in; $i++ ) { my $temp = $num[$i]; if ($units =~ m{KB}) { $units =~ s{KB}{kB}g } $temp =~ s{$units}{}g; $temp =~ s{ $}{}g; chomp $temp; push @dig, $temp }

    $units doesn't have to be modified every time the loop iterates, in fact it can only be modified once anyways:

    $units =~ s/KB/kB/g; for my $i ( @num ) { my $temp = $i; $temp =~ s/$units//g; $temp =~ s/ $//g; chomp $temp; push @dig, $temp; }



    $sum = $sum + $dig[$i];

    That is usually written as:

    $sum += $dig[ $i ];



    if ($skip !~ "" && $skip !~ m{,}) {

    According to perlop:

    The empty pattern // If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead. In this case, only the "g" and "c" flags on the empty pattern is honoured - the other flags are taken from the original pattern. If no match has previously succeeded, this will (silently) act instead as a genuine empty pattern (which will always match).

    Which means that $skip !~ "" will be $skip !~ m{yes|y}i if $ARGV[2] =~ m{yes|y}i matched (or the last previously successful match.)

    What you probably want is:

    if ( length $skip && $skip !~ /,/ ) {



    elsif ($si > 0) {

    Or (what this really means):

    elsif ( @sks ) {
Re: Utility to calculate best way to archive Dir to DVD
by ambrus (Abbot) on Aug 13, 2013 at 12:14 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://1047606]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-23 18:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found