Prev: How to get the composite type information?
Next: FAQ 8.14 How do I modify the shadow password file on a Unix system?
From: Peng Yu on 5 Jun 2010 18:30 I want to use bash instead of sh because I need the process substitution. But by default perl use sh instead of bash. Is there a way to let perl use bash? #!/usr/bin/perl use warnings; use strict; open(IN, 'ls <(echo main.txt) |'); foreach (<IN>) { }
From: Alan Curry on 5 Jun 2010 19:24 In article <f3faff34-3471-4628-9b7e-6c713b91ce6a(a)a20g2000vbc.googlegroups.com>, Peng Yu <pengyu.ut(a)gmail.com> wrote: >I want to use bash instead of sh because I need the process >substitution. But by default perl use sh instead of bash. Is there a >way to let perl use bash? > >#!/usr/bin/perl > >use warnings; >use strict; > >open(IN, 'ls <(echo main.txt) |'); >foreach (<IN>) { >} call bash -c 'your command' explicitly, like this: open IN, '-|', $shell, '-c', $cmd Where $shell is 'bash' or '/usr/bin/bash' or something else that names the shell you want, and $cmd is the 'ls <(echo main.txt)' string -- Alan Curry
From: Ben Morrow on 5 Jun 2010 20:15
Quoth Peng Yu <pengyu.ut(a)gmail.com>: > I want to use bash instead of sh because I need the process > substitution. But by default perl use sh instead of bash. Is there a > way to let perl use bash? > > #!/usr/bin/perl > > use warnings; > use strict; > > open(IN, 'ls <(echo main.txt) |'); This is probably not what you want here. This will give output like (on my system, for some reason, bash doesn't use /dev/fd) /var/tmp//sh-np-1275780961 In this particular case I suspect you just want backticks: open my $IN, 'ls $(echo main.txt) |'; You should also be checking the return value of open, or using autodie. Yes, even in examples, as otherwise people will assume you don't know that (unless you say something like 'error checking omitted'). > foreach (<IN>) { > } Alan Curry has already posted the simple answer (use bash explicitly, instead of allowing two-arg open to default to sh). A more portable solution that doesn't require bash (but does require a /dev/fd directory) is to do the conversion yourself: use autodie; # easier than checking every call use Fcntl; sub devfd { open my $FD, @_; # clear the close-on-exec flag, so the file stays open in the # child process my $fl = fcntl $FD, F_GETFD, 0; fcntl $FD, F_SETFD, ($fl & ~FD_CLOEXEC); # the files in /dev/fd (on systems that have that directory) are # magic, and opening them will return a dup of an existing file # descriptor return "/dev/fd/" . fileno $FD; } my $echo = devfd "-|", qw/echo main.txt/; open my $IN, "-|", "ls", $echo; It's also possible to do this with named pipes (which is what bash apparently does on my system, even though I've got a perfectly good /dev/fd directory) but this is a little harder. Apart from creating the pipe with mkfifo, you have to manually fork/exec the first child so you can point its stdout at the pipe, and you need a SIGCHILD handler to clean up the fifo when you've finished with it. Ben |