tags:

views:

345

answers:

8

Currently I am using

system("echo $panel_login $panel_password $root_name $root_pass $port $panel_type >> /home/shared/ftp");

What is the easiest way to do the same thing using Perl? IE: a one-liner.

+2  A: 

EDIT (By popular and editable demand)

http://perldoc.perl.org/functions/open.html

In your case you would have to :

  #21st century perl.
  open ($handle,'>>','/home/shared/ftp') or die("Cant open /home/shared/ftp");
  print $handle "$panel_login $panel_password $root_name $root_pass $port $panel_type";
  close ($handle) or die ("Unable to close /home/shared/ftp");

Alternatively, you could use the autodie pragma (as @Chas Owens suggested in comments). This way, no check (the or die(...)) part needs to be used.

Hope to get it right this time. If so, will erase this Warning.

WARNING: Do not use this code, it is full of pitfalls

Use print (not one liner though). Just open your file before and get a handle.

#!/usr/local/bin/perl
open (MYFILE, '>>data.txt');
print MYFILE "Bob\n";
close (MYFILE);

http://perl.about.com/od/perltutorials/a/readwritefiles_2.htm

In your case you would have

open (MYFILE,'>>/home/shared/ftp');
print MYFILE "$panel_login $panel_password $root_name $root_pass $port $panel_type";
close (MYFILE);
Tom
If you are going to tell people about the open function don't use the style from before 2000, use the three argument version of open and lexical filehandles. And for the sake of sanity, check the return codes (or use the autodie pragma): open my $fh, ">>", "/home/shared/ftp" or die "could not open /home/shared/ftp: $!"; print {$fh} "blah"; close $fh or die "could not close /home/shared/ftp: $!";
Chas. Owens
I ended up using this way, but my question is why is the style "after 2000" so much better?
BHare
@Brian - from perlopentut - There is also a 3-argument version of open, which lets you put the special redirection characters into their own argument: open( INFO, ">", $datafile ) || die "Can't create $datafile: $!";In this case, the filename to open is the actual string in $datafile , so you don't have to worry about $datafile containing characters that might influence the open mode, or whitespace at the beginning of the filename that would be absorbed in the 2-argument version. Also, any reduction of unnecessary string interpolation is a good thing.
@Chas, I don't think it's actually necessary to check for errors in sample code such as this. A comment such as "# skipped error checking because it's an example" should suffice. Error checking, while important, clutters up the more important part of the answer, which is the actual solution.
Nathan Fellman
@Nathan Fellman no, error checking is always important. Most people just copy and paste the code changing only the variable names.
Chas. Owens
@Brian in addition to the docs kevinadc pointed out, bareword filehandles are globally scoped where as lexical filehandles only exist in the scope they are declared in. They also are easier to pass to functions and close themselves when they go out of scope. The two argument version of open and bareword filehandles were mistakes that are only left in the language for backwards compatibility. They were replaced in Perl 5.6 (circa 2000), but people still mistakenly use the old ones because of all of the sample code out there.
Chas. Owens
Does anyone know, how we can get the page he cites, to be corrected?
Brad Gilbert
@ Brad: The About.com page has no author information that I can find. While we are dreaming big, how can we get all of perldoc itself to stop using bareword filehandles? (See perldoc -f open and perldoc perlopentut, for example.)
Telemachus
@People > After reading all your comments, i'm evaluating the posibility of deleting this answer, as it seems quite wrong. What to you think, delete or edit? Tom, the poster.
Tom
+8  A: 

You might find IO::All to be helpful:

use IO::All;
#stuff happens to set the variables
io("/home/shared/ftp")->write("$panel_login $panel_password $root_name $root_pass $port $panel_type");
Chas. Owens
Telemachus
Point, I was assuming people would know that they have to use modules.
Chas. Owens
+4  A: 
(open my $FH, ">", "${filename}" and print $FH "Hello World" and close $FH) 
    or die ("Couldn't output to file: ${filename}: $!\n");

Of course, it's impossible to do proper error checking in a one liner... That should be written slightly differently:

open my $FH, ">", "${filename}" or die("Can't open file: ${filename}: $!\n");
print $FH "Hello World";
close $FH;
Matthew Scharley
Your code makes me think you aren't using the strict pragma (the lack of a my in front of $FH is the tip off) and you should be using the three argument version of open, not the dangerous two argument version. What would happen if $filename was ">foo"?
Chas. Owens
I usually use strict, but this was a quick example that I didn't even run through perl, and if he knows enough to know to use strict, but not how to fix the warning this code would throw, then he's got more problems then simply writing to a file.
Matthew Scharley
As for the filenames... It's been a while since I wrote serious Perl, but oh well. Good point.
Matthew Scharley
+11  A: 

Why does it need to be one line? You're not paying by the line, are you? This is probably too verbose, but it took a total of two minutes to type it out.

#!/usr/bin/env perl
use strict;
use warnings;

my @values = qw/user secret-password ftp-address/;

open my $fh, '>>', 'ftp-stuff'          # Three argument form of open; lexical filehandle
  or die "Can't open [ftp-stuff]: $!";  # Always check that the open call worked

print $fh "@values\n";     # Quote the array and you get spaces between items for free

close $fh or die "Can't close [ftp-stuff]: $!";
Telemachus
What, no check to see if print succeeded (grin)? Seriously, the autodie pragma (while not part of the Perl core), removes the need to explicitly check the return values of open and close: http://search.cpan.org/dist/autodie/lib/autodie.pm
Chas. Owens
Yup, and I have begun to use it in my own code. I don't always remember, but I'm working on that. But in code for someone asking "How can I print to a file?" I figure that baby steps are in order. Modules are a later recommendation.
Telemachus
A: 

For advanced one-liners like this, you could also use the psh command from Psh, a simple pure Perl shell.

 psh -c '{my $var = "something"; print $var} >/tmp/out.txt'
snoopy
A: 

Some good reading about editing files with perl:

FMTYEWTK About Mass Edits In Perl

+5  A: 

You might want to use the simple File::Slurp module:

use File::Slurp;

append_file("/home/shared/ftp",
    "$panel_login $panel_password $root_name $root_pass ".
    "$port $panel_type\n");

It's not a core module though, so you'll have to install it.

+1 for mentioning `File::Slurp`.
Sinan Ünür
Brian is appending to his file, not overwriting it, so should use `append_file` instead of `write_file`. But still, File::Slurp ftw.
Dave Hinton
Changed to append_file and added a new-line. Thanks Dave.
A: 

I use FileHandle. From the POD:

use FileHandle;
$fh = new FileHandle ">> FOO"; # modified slightly from the POD, to append
if (defined $fh) {
    print $fh "bar\n";
    $fh->close;
}

If you want something closer to a "one-liner," you can do this:

use FileHandle;
my $fh = FileHandle->new( '>> FOO' ) || die $!;
$fh->print( "bar\n" );
## $fh closes when it goes out of scope
gpojd
(FileHandle->new('>>FOO')||die $!)->print("bar\n"):-D
Massa