Question

Here's my code

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

my $file = $ARGV[0];
system('wc -l $file');
print "\nprinting alpha \n";
sleep 1;
exit;

After I run (in tcsh shell) perl script.pl /path/to/file I don't see printing alpha until I press Ctrl+C. Even when I add another statement $|=1 either before or after system call, the behaviour remains the same.

What is happening?

Was it helpful?

Solution

You are executing the shell command

wc -l $file

The shell has no variable $file defined, so that's the same as

wc -l

This causes the shell to execute wc with the lone arg -l. With no file name provided, wc in turn reads from STDIN until you kill it with SIGINT from Ctrl-C.


You were perhaps aiming for

system("wc -l $file");   # XXX

but that's wrong too. That doesn't pass the args -l and the value of $file to wc. Consider what would happen if a file name with a space in it was provided.

To build a shell literal that results in the correct file name, you could use

use String::ShellQuote qw( shell_quote );
system(shell_quote('wc', '-l', $file));

But a better option is to avoid the shell and execute wc directly, passing to it the values you want without having to build a shell command.

system('wc', '-l', $file);

OTHER TIPS

Because the single quotes prevent interpolation of $file. Change to double quotes.

What is happening is that the string is being executed without substituting a value for $file. When the shell gets this it looks for a shell variable $file which does not exist, so it executes the command with no file. This causes wc to read from stdin, resulting in the behavior you see.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top