Определите, используется ли файл в Perl в Windows

Я пишу некоторый Perl, который берет телепередачи, записанные на Windows Media Center, и перемещает/переименовывает/удаляет их в зависимости от определенных критериев.

Так как Perl работает справедливо часто, я хотел бы чисто определить, используется ли файл (другими словами, шоу находится в процессе того, чтобы быть зарегистрированным), таким образом, я могу постараться не делать что-либо с ним.

Мой существующий метод смотрит на состояние файла (использующий "статистику") и сравнивает его снова после 5 секунд, как так:

sub file_in_use
{
  my $file = shift;

  my @before = stat($file);
  sleep 5;
  my @after = stat($file);

  return 0 if ($before ~~ $after);
  return 1;
 }

Это, кажется, работает, но я сознателен, что существует, вероятно, лучший и более чистый способ сделать это.

Можно ли советовать?

5
задан Richard 10 July 2010 в 17:36
поделиться

2 ответа

Если процесс записи блокирует файл, вы можете попытаться открыть его в режиме чтения-записи и посмотреть, не завершится ли он с помощью ERROR_SHARING_VIOLATION как GetLastError (доступ осуществляется через специальную переменную Perl $ ^ E ).

Например:

#! /usr/bin/perl

use warnings;
use strict;

sub usage { "Usage: $0 file ..\n" }

die usage unless @ARGV;

foreach my $path (@ARGV) {
  print "$path: ";

  if (open my $fh, "+<", $path) {
    print "available\n";
    close $fh;
  }
  else {
    print $^E == 0x20 ? "in use by another process\n" : "$!\n";
  }
}

Пример вывода с Dir100526Lt.pdf , открытый программой чтения Adobe:

C:\Users\Greg\Downloads>check-lock.pl Dir100526Lt.pdf setup.exe
Dir100526Lt.pdf: in use by another process
setup.exe: available

Имейте в виду, что каждый раз, когда вы сначала проверяете условие, а затем действуете на его основе test, вы создаете состояние гонки .Похоже, что худшее, что это может вас укусить в вашем приложении, находится в следующей неудачной последовательности:

  1. проверьте видео на доступность, как указано выше
  2. ответ: доступно!
  3. тем временем запускается рекордер и снова блокирует видео
  4. в вашей программе, вы пытаетесь переместить видео, но это не удается из-за нарушения совместного доступа
8
ответ дан 14 December 2019 в 01:01
поделиться

Единственное улучшение, которое я бы предложил, - это stat сразу всех ваших файлов, поэтому вам нужно спать только 5 секунд один раз вместо того, чтобы спать 5 секунд каждый раз. файл:

my (%before, %after);
foreach my $file (@files_that_might_be_in_use) {
    $before{$file} = [ stat $file ];
}
sleep 5;
foreach my $file (@files_that_might_be_in_use) {
    $after{$file} = [ stat $file ];

    if ( $before{$file} ~~ $after{$file} ) {
        # file is not in use ... 
    } else {
        # file is in use ... 
    }
}
1
ответ дан 14 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: