нет такого файла или каталога с системными вызовами perl

Я пытаюсь запустить сценарий Perl, который считывает имена файлов из стандартного ввода и вызывает du с помощью системной команды. Когда я запускаю команду du в командной строке, она работает нормально, но когда du вызывается в сценарии perl с помощью system(), я получаю «Нет такого файла или каталога». В имени файла есть пробелы и апостроф, которые я избегаю перед передачей в скрипт perl. Сам perl-скрипт ОЧЕНЬ прост:

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

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

Я также использую сценарий оболочки, чтобы избежать имени файла. Однострочный скрипт выглядит следующим образом:

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

пример имени файла до и после его запуска через sed:

/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 

Я пробовал с пробелами и апострофом и без них.

вывод:

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

одна важная вещь, я запускаю это на Mac OS X 10.95 в окне терминала. Перл v5.16.2

Вы можете спросить, что я пытаюсь сделать. Я пытаюсь получить размер отдельных резервных копий Mac TimeMachine.

так может ли кто-нибудь сказать мне, что мне нужно?


person Community    schedule 05.06.2015    source источник
comment
В конце каждого имени файла есть новая строка. Или, вернее, нет.   -  person William Pursell    schedule 05.06.2015
comment
quotemeta твой друг здесь. perldoc.perl.org/functions/quotemeta.html   -  person Sobrique    schedule 05.06.2015
comment
В форме списка system вам не нужно экранировать имена файлов.   -  person Jim Davis    schedule 05.06.2015


Ответы (2)


Сообщение об ошибке говорит вам, что вам нужно. Он пытается открыть файл, имя которого заканчивается на \n. Попробуйте chomp.

Но на самом деле вам следует использовать find w/--exec или xargs или обход в Perl с помощью File::Find. Это чрезвычайно хрупкий способ достижения ваших целей.

find /path/to/root/dir -type f -exec du -sh {} \;
person William Pursell    schedule 05.06.2015
comment
Не chop пытайтесь chomp - person Sobrique; 05.06.2015
comment
Новые строки гарантированно будут там, и именно тогда chop уместно. - person William Pursell; 05.06.2015
comment
С другой стороны, прирост производительности chop по сравнению с chomp здесь совершенно неуместен, поэтому нет причин избегать chomp, кроме потери удара в кодовом гольфе. - person William Pursell; 05.06.2015
comment
@WilliamPursell: chomp - правильный вызов. Если ввод завершается Ctrl-D вместо Enter, то не будет завершающей новой строки. chop имеет место, но его нет здесь - person Borodin; 05.06.2015
comment
к сожалению, список не может быть получен из find. Я полагаюсь на tmutil, утилиту TimeMachine, для создания списка. Благодарность - person ; 08.06.2015
comment
Я удалил необходимость tmutil. найти слова здорово. Просто удивительно, что можно сделать с find! - person ; 08.06.2015

Содержимое $line1 включает новую строку, которую вы ввели для завершения строки. Это приведет к несоответствию, если вы попытаетесь найти файл с таким именем, поэтому удалите его с помощью chomp

Также лучше всего объявлять переменные как можно позднее — предпочтительно в первой точке их использования — а не в блоке вверху программы.

use strict;
use warnings;

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