Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
Just another Perl shrine
 
PerlMonks  

Simple Perl Backup help

by laxman526 (Initiate)
on Aug 03, 2012 at 19:17 UTC ( #985327=perlquestion: print w/ replies, xml ) Need Help??
laxman526 has asked for the wisdom of the Perl Monks concerning the following question:

Hey Everyone,

I'm a Network Admin and just literally picked up programming within the last month. I'm loving Perl so far. But due to my lack of experience, I'm finding it difficult to write even the simplest if and else statements.

Here is my very first program I wrote last night. Basically it takes an array of directories to back up, checks if the dirs exist then prompts a user for a "yes" or "no" response to back up. Then tarballs the directories and moves them to a different server.

My issue is testing user input. I want the code to shorten up a bit. I'm hoping someone will have some insight into this. Also, I'm going to make this an rsync backup script at one point, but wanted to practice with tar and commands first.

Also, I encourage general formatting, syntax, or anything else to help me along the way! Thanks everyone!

#!/usr/bin/perl use warnings; use POSIX qw(strftime); use vars qw( $now_string @backup_dirs $dir $command_tar $dest $filenam +e); @backup_dirs = ( "/home/justin" , "/usr/src" ); foreach $dir ( @backup_dirs ) { unless ( -d $dir ) { die "The directory $dir does not exist!\n$!"; } } foreach ( @backup_dirs ) { print "$_\n"; } while (1) { print "Are you sure you want to backup these directories?\n"; print "Please select yes/no.\n"; my $input = <>; chomp($input); if ( $input eq 'n' ) { die "Program is shutting down.\n"; } if ( $input eq 'y' ) { print "Backup is beginning......\n"; last; } if ( $input eq 'yes' ) { print "Backup is beginning......\n"; last; } if ( $input eq 'no' ) { die "Program is shutting down.\n"; } } $now_string = strftime("%Y%m%d_%H%M", localtime); $filename = "bkp-".$now_string."tar.gz"; $command_tar = "tar cfvz $filename @backup_dirs"; system($command_tar); unless ( -e $filename ) { die "This file did not archive correctly.\n$!"; } print "Where do you want to back this up to?\n"; $dest = <>; chomp($dest); unless ( -d $dest ) { die "This is not a valid directory.\n$!"; } print "Backing up data to $dest now.........\n"; $command_copy = system( "mv -v $filename $dest" ); system("$command_copy"); print "Backup complete!\n";

Comment on Simple Perl Backup help
Download Code
Re: Simple Perl Backup help
by moritz (Cardinal) on Aug 03, 2012 at 19:26 UTC

    If your perl is of version 5.10 or later, you can add

    use 5.010;

    at the start of your script, and substitute all your  print "something\n"; lines with say "something". Looks like a small code, but it does make it more fun to read and write.

    As for your original question, you can write something like

    if ($input =~ /^(y|yes)$/) { say "Backup is beginning..."; last; } elsif ($input =~ /^(n|no)$/) { die "Program is shutting down.\n"; } else { say "This is not a valid answer."; say "Please enter 'yes' or 'no'"; }

    This uses regexes to test for several values at once, laading to fewer branches with duplicate code. You could also write

    if ($input eq 'y' || $input eq 'yes') { say "Backup is beginning..."; last; }

    if you don't want to use regexes.

    Finally you should check the return value of system. Just because the backup file exists doesn't mean the backup was successfull. There could be a full file system, file system corruption, permission errors or other problems -- in which case tar will return a non-zero return code, which you should catch. See system for the full documentation on how to do that.

      Thanks moritz! This is really good information. Thanks for your timely response.

      I am definitely working to wrap my head around regexes. I will take that into consideration.

      Also, thanks for the input on error checking. I never took that into consideration either. I will get to work on that as well.

      Back to coding....thanks again.

Re: Simple Perl Backup help
by toolic (Chancellor) on Aug 03, 2012 at 19:30 UTC
    Another way using perldoc perlre (case-insensitive and only looks at 1st character):
    if ( $input =~ /^n/i ) { die "Program is shutting down.\n"; } elsif ( $input =~ /^y/i ) { print "Backup is beginning......\n"; last; }
Re: Simple Perl Backup help
by davido (Archbishop) on Aug 03, 2012 at 19:46 UTC

    A lot of your input code can be reduced to:

    use IO::Prompt::Tiny qw/prompt/; my $answer = prompt("Yes or no? (y/n)", "n");

    ...by using IO::Prompt::Tiny. Then your user-input code could be reduced to the following:

    if( prompt( "Backup $path? (y/n)", 'y' ) =~ m/^y/i ) { print "Backup beginning...\n"; perform_backups( @backup_dirs ); print "Backup complete.\n"; } else { print "No backups performed. Exiting.\n" } sub perform_backups { my @directories = @_; # Your backup code here. }

    You could also warn instead of die if one or more backups failed, and then just keep on processing the rest (or prompt for what to do).<?p>

    prompt() is convenient to use anywhere that user input is desired. If you need stronger input validation, IO::Prompt provides a richer set of tools, but adds some complexity.


    Dave

      Great info! Thank you so much. I'll add these tools to my Perl arsenal.

Re: Simple Perl Backup help
by ww (Bishop) on Aug 03, 2012 at 20:22 UTC

    You already have a couple three good answers, but what struck me was your use of invisible ink for             on line 3. It's really bad practice to put your use strict; directive in invisible ink.

    Seriously, until you're quite expert, strict (or, for 5.14, a use 5.014 -- which may be good, with the appropriate version value, back to 5.010) will help you find your mistakes and save you from much grief.

      thanks ww. Yes, you're right, I am missing strict. I had encountered an error with it when I was using strftime. I just re-ran the script w/ the use strict; and came out fine. Yes, being a noob, I should def. use all of the syntax and error checking functions as much as possible.

      Thanks again for all of your input.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://985327]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (11)
As of 2014-04-24 09:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (565 votes), past polls