Этот Perl-скрипт обрабатывает один файл. Кроме того, эта строка, переданная в оболочку с помощью os.system
, не может быть развернута в допустимую команду со списком файлов, как предполагалось с глобусом оболочки *
.
Вместо этого создайте список файлов в Python, используя os.listdir
или glob.glob
или os.walk
. Затем выполните итерацию по списку и вызовите этот сценарий Perl для каждого файла, если он должен обрабатывать только один файл за раз, или измените сценарий Perl для обработки нескольких файлов и запускайте его один раз со всем списком.
Чтобы сохранить текущий Perl-скрипт и запускать его для каждого файла
import os
data_path = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"
for file in os.listdir(data_path):
if not file.endswith(".txt"):
continue
print("Processing " + file) # better use subprocess
run_perlscript = "perl " + " perlscript.pl " + \
data_path + file + " >> " + output_path + "output.txt"
os.system(run_perlscript)
Сценарий Perl необходимо переписать, чтобы избежать ненужного дублирования кода.
Однако лучше использовать модуль subprocess для запуска и управления внешними командами. Это рекомендуется даже в самой документации os.system .
Например
import subprocess
with open(output_path + "output.txt", "a") as fout:
for file in os.listdir(path):
if not file.endswith(".txt"):
continue
subprocess.run(["perl", "script.pl", data_path + file], stdout=fout)
, где файл открывается в режиме добавления ("a"
) после перенаправления вопроса >>
.
Рекомендуемый subprocess.run доступен начиная с python 3.5; в противном случае используйте Popen .
Другой, возможно, «правильный» вариант - настроить скрипт Perl так, чтобы он мог обрабатывать несколько файлов. Тогда вам нужно только запустить его один раз, со всем списком файлов.
use strict;
use warnings;
use feature 'say';
use open ':std', ':encoding(UTF-8)';
foreach my $filename (@ARGV) {
say "Processing $filename";
my %count;
open my $fh, '<', $filename or do {
warn "Can't open '$filename': $!";
next;
};
while (<$fh>) {
$count{ lc $1 }++ while /(\w+)/g;
}
close $fh;
my $prn_cnt = 0;
foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count) {
print "$count{$word} $word\n" if $prn_cnt++ < 10;
}
}
Это выводит предупреждение на файл, который он не может открыть, и переходит к следующему. Если вы хотите, чтобы сценарий завершал работу с любым неожиданным файлом, замените or do { ... };
на исходный die
.
Тогда (используя glob.glob в качестве примера сейчас)
import subprocess
data_path = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"
files = glob.glob(data_path + "*.txt")
with open(output_path + "output.txt", "a") as fout:
subprocess.run(["perl", "script.pl", files], stdout=fout)
Так как весь список передается в качестве аргументов команды, предполагается, что нет (больших) тысяч файлов, что превышает некоторые ограничения длины для каналов или командной строки.