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

#!perl -w # "-w" turns on all sorts of warnings about probable + errors. $dir = "r:\\\\40K\\"; sub listdirectory { local($dir); local(@lines); local($subdir); local($lvl_counter); local($list_length); $dir = $_[0]; if(opendir (DIR, $dir)) { @lines = readdir (DIR); closedir (DIR); $lvl_counter = 2; $list_length = ( scalar @lines ); while ($lvl_counter < $list_length) { $subdir = $dir."\\".$lines[$lvl_counter]; if(opendir (SUBDIR, $subdir)) { closedir (SUBDIR); &listdirectory($subdir); } else { print "$subdir\n"; } $lvl_counter++; } } } &listdirectory($dir);

OUTPUT:

read_import_test.pl r:\\40K\\A400332S1_05.pdf r:\\40K\\A400332S2_05.pdf r:\\40K\\A400332S3_05.pdf r:\\40K\\A400396S1_07.pdf r:\\40K\\A400396S2_07.pdf

How Can I remove the PATH and get just the basename?
How can I get just *.pdf, if this directory had different files in it? (like *.tif files)
I tried using File::Spec::Win32 and CWD but had problems?
Can someone tell me when I "should" download mods and use them.
And when I can just use scripts without modules?

Please let me know if you need more details and if you can help.
TIA!
Scott

20050207 Janitored by Corion: Added formatting

Replies are listed 'Best First'.
Re: Creating a script to pass dir name, basename and just *.pdf & *.tif files
by Zaxo (Archbishop) on Feb 07, 2005 at 16:25 UTC

    File::Find and glob can be used very effectively for that.

    use File::Find; sub listdirectory { my ($basedir, $basename) = @_; my @files; find sub { -d && push @files, glob "${File::Find::name}/${basename}*.{pdf,tif}"; }, $basedir; @files; }
    That will return a list of all the paths to matching files under the base directory.

    Your use of local suggests that you are following somebody's Perl 4 tutorial. Call my instead to get scoped temporary variables in Perl 5.

    After Compline,
    Zaxo

      Hi Zaxo, Thanks for the quick reply! The code works great on my machine with Perl 5.8...but, I am trying to run on a machine that has this version of perl! (This all runs in a "modified" DOS cmd window that sets all kinds of PATH's for the custom application)

      C:\Perl\Weir_scripts>perl -c import_prod.pl Ambiguous use of eval => resolved to "eval" => at ..\lib/re.pm line 81. Perl 5.006 required--this is only version 5.00307, stopped at ..\lib/File/Basena me.pm line 142. BEGIN failed--compilation aborted at ..\lib/File/Basename.pm line 142. BEGIN failed--compilation aborted at import_prod.pl line 3.
      C:\Perl\Weir_scripts>perl -v This is perl, version 5.003_07

      So, I installed 5.8 & now have "two" versions of perl on this machine. But, some consultants came in and installed this "old" version on the machine for use with their exisiting scripts! Can I still upgrade without causing harm to the old stuff? I know I can remove the old paths in the enviroment section in Windoze. But, the application may not know where to look....sigh.

      I need these ENV vars: C:\Perl\Weir_scripts>set IMAN IMAN_BIN=c:\ugs\tceng912\bin IMAN_DATA=c:\ugs\imandata\testdata IMAN_DB_CONNECT=infodba:tbwiabd@test IMAN_DISABLE_FLASH=true IMAN_HELP_FILE=c:\ugs\tceng912\web\htdocsimanhelp\imanhelp.hlp IMAN_INCLUDE=c:\ugs\tceng912\include IMAN_INIT_DIR=C:\DOCUME~1\ADMINI~1.WIL\LOCALS~1\Temp\1 IMAN_LANGUAGE=c:\ugs\tceng912\lang IMAN_LIBRARY=c:\ugs\tceng912\lib IMAN_LOCALIZATION_DIR=en IMAN_LOG=c:\ugs\imandata\testdata\log_wilmsntch5_test IMAN_MSG_ROOT=c:\ugs\tceng912\lang\textserver IMAN_PRINTER=lpr.exe IMAN_ROOT=c:\ugs\tceng912 IMAN_SYS_UID_DIR=c:\ugs\tceng912\lang\vt100 IMAN_TMP_DIR=C:\DOCUME~1\ADMINI~1.WIL\LOCALS~1\Temp\1 IMAN_TRACEBACK=ON IMAN_UG_DEFAULT_PART=c:\ugs\imandata\testdata\blank_english.prt IMAN_USER_TOOLS=c:\ugs\tceng912\local\tools IMAN_XML_ENCODING=ISO-8859-1
      C:\Perl\Weir_scripts>set ORACLE ORACLE_HOME=c:\ugs\tceng912 ORACLE_SERVER=wilmsntch5 ORACLE_SID=test

      Here is where they store and access the perl binary: C:\UGS\tceng912\bin>dir perl.exe Volume in drive C has no label. Volume Serial Number is 0CF2-5BB1 Directory of C:\UGS\tceng912\bin 07/02/1998 03:32 PM 87,040 perl.exe 1 File(s) 87,040 bytes 0 Dir(s) 12,339,765,248 bytes free
      C:\UGS\tceng912\bin>perl -v This is perl, version 5.003_07

      What can I do? I am afraid that I can;t jsut copy the new 5.8 Perl binary(perl.exe) to this dirsctory and go from there. Or can I? Are there depends, dll's or the like to worry about? Even application depends too?
      Any help is greatly appreciated!! Thank-you.

        Besides shooting the consultants?

        Perl 5.003_07 is old! Perl 5.004 was released in May 1997, if my reckoning is right. Did those guys clobber your 5.8 binary? If that's all, you can move theirs to /path/to/perl5_003_07.exe and recopy your proper binary back in. With ActiveState, the binary is version-labeled, so they probably didn't bother to clobber that unless they uninstalled the whole thing. Shooting's too good for them if they did that.

        I'm not too familiar with winders, but you might be able to associate just their crusty script with their old perl, and let your modern installation handle everything else. On unix, all you would need to do is change the splatline.

        I wonder if their old perl is even a complete installation?

        You have a better chance of running old scripts on new perl than the reverse. If the contractor script won't run on new perl, you should take a hard look at its quality. If the consultants haven't updated their script in eight years of improvements to perl, consider their quality.

        Update: Sorry, there's not much more I can say without looking at the scripts and the details of your installation. You can make output like that look better on pm by enclosing it in <code> . . . </code> tags. They are sort of super pre tags.

        After Compline,
        Zaxo

Re: Creating a script to pass dir name, basename and just *.pdf & *.tif files
by brian_d_foy (Abbot) on Feb 07, 2005 at 16:05 UTC

    I think you want File::Basename, which comes with perl, so you should already have it.

    You download and use modules when you need them. That's about the best answer you'll get. :)

    --
    brian d foy <bdfoy@cpan.org>
Re: Creating a script to pass dir name, basename and just *.pdf & *.tif files
by holli (Abbot) on Feb 07, 2005 at 16:08 UTC
    How Can I remove the PATH and get just the basename? How can I get just *.pdf, if this directory had different files in it? (like *.tif files)
    1) use File::Basename
    use File::Basename qw(fileparse); my ($path,$file,$suffix) = fileparse ("filename", "\.[^\.]+$");
    2) You have a list of filenames. Just grep those out you want:
    @lines = grep { /\.tif$/i } readdir (DIR);
    holli, /regexed monk/
Re: Creating a script to pass dir name, basename and just *.pdf & *.tif files
by friedo (Prior) on Feb 07, 2005 at 16:06 UTC
    Welcome to PerlMonks.

    Please see [id://Writeup Formatting Tips] to learn how to use the nifty code tags. It's good that you have warnings on, but you should also be using strict. You should also not be using local variables in your subroutine, but lexical (or my) variables. See Coping with Scoping.

    To get the basenames of files, you can use the CPAN module File::Basename. Since you appear to want to do a recursive traversal of a directory tree, I reccomend using a module like File::Find or File::Finder instead of rolling your own. You can also get a list of files that match a pattern with glob or by doing a regex match while you loop over the filenames.