Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

A looping question

by Anonymous Monk
on Sep 10, 2010 at 08:36 UTC ( [id://859605]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm having difficulty coding a function in Perl and need some assistance. Here's the pseudo code for what I would like to achieve.
prompt user to enter a directory name Check if directory name exists If it does prompt user again and ask if the contents of the dir can be + overwritten. If it can continue with rest of program otherwise loop round again asking the same questions and doing the sam +e checks again . This bit may need to be run several times depending +on whether the user enters an existing dir or not.
I'm struggling with the code for this. I've tried varoius things. The closest I've got is
use warnings; use strict; use Term::Prompt; use File::Find; no warnings 'File::Find'; sub Wanted; my ($dirname,$ans); $basedir="/dmp/backup"; $dirname = prompt('e', 'Enter a dir name', 'e.g. regression-EO +DDAY1', '','[A-Za-z0-9_-]+' ); # Check whether the dir already exists if find(\&Wanted, $basedir) { $ans = prompt('y', 'That dir already exists, do you wi +sh to overwrite the existing contents ?','[y/n]','n'); if ($ans = 1) { $dirname = prompt('e', 'Enter a dir name', 'e. +g. regression-EODDAY1', '','[A-Za-z0-9_-]+' ); } if find(\&Wanted, $basedir) { $ans = prompt('y', 'That dir already exists, d +o you wish to overwrite the existing contents ?','[y/n]','n'); if ($ans = 1) { $dirname = prompt('e', 'Enter a dir na +me', 'e.g. regression-EODDAY1', '','[A-Za-z0-9_-]+' ); } } } sub Wanted { my $dir = $File::Find::name; print if /$dirname/ ; return; }
It doesn't work. I'm fairly new to Perl and I suspect the code above reflects that ! This is on Unix (Solaris) . Any help is welcome

Replies are listed 'Best First'.
Re: A looping question
by graff (Chancellor) on Sep 10, 2010 at 13:32 UTC
    I always find that that it's a real drag having to supply any keyboard input (beyond a basic "y/n" confirmation) to a perl script while it's running. (Same goes for any command-line tool.) The more such input is needed, the sooner I tend to regard the tool as not worth using. (Update: Of course, I'm not referring to tools that actually involve shell-like interaction with the user, such as the perl debugger or the cpan shell; I'm just talking about tools where all the needed information can be specified at start-up.)

    A decent command-line shell offers things like path-name completion (type a few characters and hit the tab key), and command history with easy recall(/edit)/rerun of previous commands, to minimize the amount of typing needed.

    IMHO, the start of your script should just be:

    use strict; use warnings; my $Usage = "Usage: $0 [-f] directory_path\n"; my $force; if ( @ARGV > 1 and $ARGV[0] eq '-f' ) { $force = shift; } die $Usage unless ( @ARGV == 1 ); my $dirname = shift; if ( -e $dirname and ! $force ) { die "$dirname exists. Use '-f' option to delete the existing $dir +name\n$Usage"; } ...
    That way, if the person typed an existing path name by mistake, they just recall, edit and rerun the command line. If they already know that the existing path name should be deleted/replaced, they include "-f" on the command line. Now, the operation can be run as part of in any shell script (or another perl script), and can run without manual intervention (e.g. as a scheduled task).

    If there are other run-time user decisions to be handled, which should be provided by means of additional command-line options, then you'll want to get acquainted with Getopt::Long or Getopt::Std (which come as core modules with Perl).

Re: A looping question
by FunkyMonk (Chancellor) on Sep 10, 2010 at 09:52 UTC
    Have a look at perl's file test functions. You can use -d $foo to test if a directory exists. That would simplify your problem.
      In this context, using "-e" would be better, since a given name might exist as a data file (or symbolic link).
      Thanks, this made the job a whole lot easier
Re: A looping question
by JavaFan (Canon) on Sep 10, 2010 at 09:18 UTC
    I've no idea what you want to test in Wanted; the function always returns false. It also assigns to $dir, which you then never use. You also match $dirname against $_ - I do not know why.

    Assuming you want a subdirectory of the current directory, the following should do the trick:

    use Term::Prompt; use strict; use warnings; my $dirname; { $dirname = prompt('s', 'Enter a dir name', 'e.g. regression-EODDAY1', '', sub {$_[0] =~ /^[A-Za-z0-9_-]+$/ && -d $_[0]}); redo unless prompt('y', 'That dir already exists, do you wish to ' + . 'overwrite the existing contents ?', '[y/n +]', 'n'); } # # Rest of program here. #
    Or you may want to rewrite the bare block as a repeat-until loop.
Re: A looping question
by Anonymous Monk on Sep 10, 2010 at 08:49 UTC
    Code posted above should have looked like this
    use warnings; use strict; use Term::Prompt; use File::Find; no warnings 'File::Find'; sub Wanted; my ($dirname,$ans); $basedir="/dmp/backup"; $dirname = prompt('e', 'Enter a dir name', 'e.g. regression-EO +DDAY1', '','[A-Za-z0-9_-]+' ); # Check whether the dir already exists if (find(\&Wanted, $basedir)) { $ans = prompt('y', 'That dir already exists, do you wi +sh to overwrite the existing contents ?','[y/n]','n'); if ($ans == 1) { $dirname = prompt('e', 'Enter a dir name', 'e. +g. regression-EODDAY1', '','[A-Za-z0-9_-]+' ); } if (find(\&Wanted, $basedir)) { $ans = prompt('y', 'That dir already exists, d +o you wish to overwrite the existing contents ?','[y/n]','n'); if ($ans == 1) { $dirname = prompt('e', 'Enter a dir na +me', 'e.g. regression-EODDAY1', '','[A-Za-z0-9_-]+' ); } } } sub Wanted { my $dir = $File::Find::name; print if /$dirname/ ; return; }

      First, remove that "no warning" clause, when you develop, warnings are a guide to things that may be wrong, or are wrong. As posted, the program don't compile for a strict violation, you should declare $basedir (and while at it, there's no need to declare Wanted both on the top and bottom of the program.

      Second, you check twice on the return value of "find" which goes contrary to File::Find's purpose, which is to loop over, recursively, a file tree and perform a certain action on each file/folder. Your logic should go inside the Wanted sub, rather than on an outer loop.

      "Principle of Least Astonishment: Any language that doesn’t occasionally surprise the novice will pay for it by continually surprising the expert..

        Ok , your answer has confused me. I take the point about $basedir which I've now declared and also removed the warning and only declared Wanted once. Is find the wrong thing to use to check for the existence of a file ?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (3)
As of 2024-04-25 23:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found