"no such file or directory" with perl system calls

1.6k Views Asked by At

I am trying to run a Perl script that reads in filenames from stdin and calls du using a system command. When I run the du command on the commandline it works fine but when du is called in the perl script using system() I get "No such file or directory." The filename does have spaces and an apostrophe which I escape before passing it into the perl script. The perl script itself is VERY simple:

use strict; use warnings;
my $line1;
my @tmutil_args;

while($line1 = <>){
    @tmutil_args = ("du", "-sh", $line1);
    system(@tmutil_args);
}

I also use a shell script to escape the filename. The one line script is as follows:

s/[\' ]/\\&/g

a sample filename before and after it is run through sed is:

/Volumes/Mac Mini Backup 4TB/Backups.backupdb/John's Mac Mini/2015-06-04-132645

/Volumes/Mac\ Mini\ Backup\ 4TB/Backups.backupdb/Pete\'s\ Mac\ Mini/2015-06-04-132645 

I have tried with and without escaping the spaces and apostrophe.

the output is:

du: /Volumes/Mac\ Mini\ Backup\ 4TB/Backups.backupdb/Pete\'s\ Mac\ Mini/2015-06-04-132645
: No such file or directory

one important thing, I am running this on a mac OS X 10.95 in a terminal window. Perl v5.16.2

you might ask what I am trying to do. I am trying to get the size of the individual Mac TimeMachine backups.

so can anyone tell me what I need?

2

There are 2 best solutions below

6
On

The error message tells you what you need. It is trying to open a file whose name ends with \n. Try chomp.

But really you should be using find w/--exec or xargs, or traversing in perl with File::Find. This is an extremely fragile way to accomplish your goals.

find /path/to/root/dir -type f -exec du -sh {} \;
0
On

The contents of $line1 includes the newline that you typed to terminate the string. That will cause a mismatch if you try to find a file with that name, so remove it using chomp

It is also best to declare your variables as late as possible — preferably at their first point of use — and not in a block at the top of the program

use strict;
use warnings;

while ( my $filename = <> ) {
    chomp $filename;
    system('du', '-sh', $filename);
}