[comp.lang.perl] Rank beginners question

frazier@oahu.cs.ucla.edu (Greg Frazier) (05/03/91)

Hi-howdy -
	I am a beginner perl hack (obviously).  I am trying
to get my script to manipulate some files in my directory.
This works
	@foo = `ls *`;
but this does not work
	@foo = `ls ~frazier`;
the error msg is
	~frazier not found

I do not understand why the '*' gets expanded correctly but
'~frazier' does not.  BTW, I am running cshell
($ENV{'SHELL'}=/bin/csh).  The man page for csh indicates that
'*' and '~[username]' are both examples of filename expansion,
so I would have assumed that if one was happening, the other
would too.  I have tried various quotes and escapes to no
avail:
	@foo = `ls '~frazier'`;
	@foo = `ls \~frazier`;
	@foo = `'ls ~frazier'`;

Any and all responses appreciated.  And, no, I do not want
to use $ENV{`HOME`}, 'cuz I'd like other people to be able
to run this script (and the files are in my directory).
-- 


Greg Frazier	frazier@CS.UCLA.EDU	!{ucbvax,rutgers}!ucla-cs!frazier

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/03/91)

In article <1991May2.173518.4194@cs.ucla.edu> frazier@oahu.cs.ucla.edu (Greg Frazier) writes:
: Hi-howdy -
: 	I am a beginner perl hack (obviously).  I am trying
: to get my script to manipulate some files in my directory.
: This works
: 	@foo = `ls *`;
: but this does not work
: 	@foo = `ls ~frazier`;
: the error msg is
: 	~frazier not found
: 
: I do not understand why the '*' gets expanded correctly but
: '~frazier' does not.  BTW, I am running cshell
: ($ENV{'SHELL'}=/bin/csh).  The man page for csh indicates that
: '*' and '~[username]' are both examples of filename expansion,
: so I would have assumed that if one was happening, the other
: would too.  I have tried various quotes and escapes to no
: avail:
: 	@foo = `ls '~frazier'`;
: 	@foo = `ls \~frazier`;
: 	@foo = `'ls ~frazier'`;
: 
: Any and all responses appreciated.  And, no, I do not want
: to use $ENV{`HOME`}, 'cuz I'd like other people to be able
: to run this script (and the files are in my directory).

You think you're running csh, but you're not.  All subshell commands
in Perl use /bin/sh, just as C's system() and popen() calls do.  To do
otherwise is to invite disaster.  You have three options:

1) Invoke csh explicity.  (Perl actually optimizes out the call to /bin/sh.)

	@foo = `/bin/csh -fc "ls ~frazier"`;

2) Use the glob syntax, which uses csh if available.

	@foo = <~frazier/*>;

3) Look up the home directory yourself.  This is portable to machines
without csh.

	$myhome = (getpwnam("frazier"))[7];
	@foo = `ls $myhome/*`;

or

	$myhome = (getpwnam("frazier"))[7];
	chdir $myhome;
	@foo = <*>;

Much faster would be

	$myhome = (getpwnam("frazier"))[7];
	opendir(DIR,$myhome);
	@foo = grep(/^\./, readdir(DIR));
	closedir(DIR);

Larry

merlyn@iwarp.intel.com (Randal L. Schwartz) (05/03/91)

In article <1991May2.173518.4194@cs.ucla.edu>, frazier@oahu (Greg Frazier) writes:
| Hi-howdy -
| 	I am a beginner perl hack (obviously).  I am trying
| to get my script to manipulate some files in my directory.
| This works
| 	@foo = `ls *`;
| but this does not work
| 	@foo = `ls ~frazier`;
| the error msg is
| 	~frazier not found
| 
| I do not understand why the '*' gets expanded correctly but
| '~frazier' does not.  BTW, I am running cshell
| ($ENV{'SHELL'}=/bin/csh).  The man page for csh indicates that
| '*' and '~[username]' are both examples of filename expansion,
| so I would have assumed that if one was happening, the other
| would too.  I have tried various quotes and escapes to no
| avail:
| 	@foo = `ls '~frazier'`;
| 	@foo = `ls \~frazier`;
| 	@foo = `'ls ~frazier'`;
| 
| Any and all responses appreciated.  And, no, I do not want
| to use $ENV{`HOME`}, 'cuz I'd like other people to be able
| to run this script (and the files are in my directory).

Backquoted strings are always interpreted with /bin/sh (thank gawwd!).

You'd need to do something like this:

$_ = 'ls ~frazier'; # suppose you want to execute this...

s#~(\w*)# (@a = getpwnam($1 || $ENV{'USER'})) ? $a[7] : $& #eg; die $@ if $@;
	## this replaces all the ~refs with what they really are.
	## warning... it can get carried away, but it's a good quick cut

@foo = `$_`;

print "Just another Perl hacker," # with not quite enough time to be clever :-)
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/