Search code examples
perlfileiosubroutine

How to pass file names to a subroutine in perl?


I'm writing a perl script and I would like to pass a file name for the output file to a subroutine.

I tried something like this:

use strict;
use warnings;

test("Output.dat");

sub test {
  my $name = @_;

  open(B, ">$name") or die "Failure \n";

  print B "This is a test! \n";
  close(B); 
}

I'm going to use the subroutine multiple times, so i have to pass the file name and cannot declare it within the subroutine.

I hope you can help me :)


Solution

  • Your problem is this line:

    my $name = @_;
    

    You are assigning an array to a scalar variable. In Perl this will give you the number of elements in the array - so I expect you're ending up with "1" in $name.

    There are a number of ways to get the first element from an array;

    my $name = $_[0]; # Explicitly get the first element
    my $name = shift @_; # Get the first element (and remove it from the array)
    my $name = shift; # Same as the previous example - shift works on @_ by default in a subroutine
    my ($name) = @_; # The parentheses make it into a list assignment
    

    The last two are the ones that you will see most commonly.

    A few more points:

    1/ You would get a better clue to the problem if you included $name in your error message.

    open(A, ">$name") or die "Failure: $name \n";
    

    Or, even better, the error message that Perl gets from your operating system.

    open(A, ">$name") or die "Could not open $name: $!\n";
    

    (I've added back the missing comma - I assume that was a typo.)

    2/ This days, it is generally accepted as good practice to use the three-arg version of open and lexical filehandles.

    open(my $output_fh, '>', $name) or die "Failure: $name \n";
    

    3/ In your example you open a filehandle called "A", but then try to write to a filehandle called "B". Is this a typo?