From BASH to Perl

Keary Suska aksuska at webflyer.com
Fri Jan 4 13:03:25 CST 2002


It is not necessary to emulate Unix commands in your Perl script unless you
are specifically trying to avoid launching a subshell. One of many simple
ways to do what you want in perl:

# $directory would be acquired from command line or whatever
$command = "find $directory -type f -ls -xdev -fstype ext2 \( -iname
'*personal*' -o -iname '.*personal*' \) -print"

# open pipe from system command
open FIND, "$command |" or die $!
while( <FIND> ) {
  # $_ will have each file name found with full path name
  # do what you want with it here
}
close FIND;

That's it. There are security and robustness considerations (checking path,
untainting input, checking SIGPIPE), but this is essentially all that is
needed.

Keary Suska
Esoteritech, Inc.
"Leveraging Open Source for a better Internet"

> From: SoloCDM <deedsmis at aculink.net>
> Reply-To: <deedsmis at aculink.net>, <pikes-peak-pm-list at happyfunball.pm.org>
> Date: Fri, 4 Jan 2002 04:56:27 -0700
> To: Pikes Peak Perl Mongers (Majordomo)
> <pikes-peak-pm-list at happyfunball.pm.org>
> Subject: From BASH to Perl
> 
> I am completely new to Perl, but not this list.  I have a BASH script
> that I want to translate to Perl, so I started with the find command.
> 
> I found a find2perl perl script, which created the following script
> from, "find2perl [directory] -type f -xdev -fstype ext2 \( -name
> '*personal*' -o -name '.*personal*' \) -print":
> 
> ===================== Begin =====================
> #! /usr/bin/perl -w
> eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
> if 0; #$running_under_some_shell
> 
> use strict;
> use File::Find ();
> 
> # Set the variable $File::Find::dont_use_nlink if you're using AFS,
> # since AFS cheats.
> 
> # for the convenience of &wanted calls, including -eval statements:
> use vars qw/*name *dir *prune/;
> *name = *File::Find::name;
> *dir = *File::Find::dir;
> *prune = *File::Find::prune;
> 
> 
> # Traverse desired filesystems
> File::Find::find({wanted => \&wanted}, '[directory]');
> exit;
> 
> sub wanted {
> my ($dev,$ino,$mode,$nlink,$uid,$gid);
> 
> (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
> -f _ &&
> !($File::Find::prune |= ($dev != $File::Find::topdev)) &&
> ($dev >= 0) &&
> (
> /^.*personal.*\z/s
> ||
> /^\..*personal.*\z/s
> ) &&
> print("$name\n");
> }
> ===================== End =====================
> 
> I was startled to find more than was necessary and some extra
> commands that I hadn't counted on (sub wanted { list }, use,
> eval, if).  I understand the reason for the eval and if statements,
> but again I know little of them.  I hadn't realized, until now,
> that it was necessary to have the use commands.  Nevertheless,
> when I executed the script, nothing was produced by the script.
> 
> The actual BASH find command was, "find [directory] -type f -ls
> -xdev -fstype ext2 \( -iname '*personal*' -o -iname '.*personal*'
> \) -print", which is piped into a while command in BASH with quotes
> around the filenames, because there are spaces in the filenames
> (filenames actually represented by variables in the BASH script).
> 
> One of my main concerns is manipulating a file and its data with
> the find and loop commands to the end of each file.
> 
> I did find, in Perl In A Nutshell by O'Reilly, where the following
> can manipulate the file:
> 
> while (<INFILE>) {
> print OUTFILE, "$_\n";
> }
> 
> I believe I understand $_ is the name as the input files data with
> a return on the end.
> 
> -- 
> Note: When you reply to this message, please include the mailing
> list/newsgroup address and my email address in To:.
> 
> *********************************************************************
> Signed,
> SoloCDM
> 




More information about the Pikes-peak-pm mailing list