【问题标题】:How do I automatically copy files to my hard disk from USB device when connected using Perl?使用 Perl 连接时,如何自动将文件从 USB 设备复制到硬盘?
【发布时间】:2011-01-23 00:40:22
【问题描述】:

我目前的想法:我需要一个可以让我访问 USB 设备的模块。另外,我需要某种守护程序来通知我的脚本任何传入的 USB 连接事件。然后我只需使用一些正则表达式来查找我想要复制的文件,然后进行复制,可能使用一些文件复制模块。

但是我用关键字“USB”搜索了CPAN,却发现周围确实很少有相关的模块,而且那个看似最有前途的模块Device::USB说它不支持Windows系统。我正在运行 Windows XP SP3,顺便说一句。

我认为这种自动化对于 Perl 来说应该不会太难。但我只是卡在那里。

有什么想法吗?或任何其他建议?谢谢:)

更新

事情并没有想象中那么容易。我确信我还有很多东西要学。但是根据我现有的 Perl 知识,我已经设法编写了一个 make-do 脚本。我是来学习的。请评论我可以改进我的代码的地方。 一如既往地感谢:)

use warnings;
use strict;
use File::Find;
use File::Copy;

my $from = 'I:/'; #Volume letter for USB drive in my OS
my $to = 'E:\Copy-to';

while (1) {
    if (-e $from) {
        last;
    }else{
        sleep(30);
    }
}

my @files;
find(sub{ push @files, $File::Find::name if /pdf$/}, $from); #Find the PDF files in the USB drive for Copying experiment

for (@files){
    copy ($_,$to);
}

【问题讨论】:

  • 搜索“USB”的问题在于,USB 基本上与它没有任何关系。您会从 HAL(而不是 USB)收到插入通知,并且您将通过文件系统(而不是 USB)与文件进行交互。
  • @hobbs,谢谢你告诉我这个。

标签: perl windows-xp usb


【解决方案1】:

最坏的情况是轮询您的卷以查找它(每隔几秒钟查找连接的驱动器)。像这样的事情在 Perl 中是相当困难的,除非你愿意亲自动手并钩入 Windows 事件系统。

显然,理想的方法是从 C 中连接到 Window 的本机 USB 通知子系统。如果您的记忆棒有 CD-ROM 仿真,您可以在上面放置一个自动运行脚本。我认为对于这类事情,你最好坚持使用 C、C++ 甚至 C#。 Perl 在 Windows 上是二等公民。

【讨论】:

  • 惊人的 Win32::API 让您可以使用几乎任何 DLL。 search.cpan.org/dist/Win32-API/API.pm 有了该模块并了解适当的 Win32 通知 API,没什么大不了的。
  • 另一个选项是 Inline::C。 search.cpan.org/dist/Inline/C/C.pod 在这里,您可以将 C API 调用包装在可从其他 Perl 代码调用的子例程中。
  • 这些人是对的。如果你把一点 C 和这个混合起来,那是完全可行的。
  • 和@daotoad,谢谢你告诉我这个。好吧,看起来事情并不像我预期的那么容易。我会试试看我能做些什么。谢谢大家:)
【解决方案2】:

如果有人(可能是像我这样喜欢在 Windows 机器上玩 Perl 的 Perl 学习者)偶然发现这篇文章,我希望她/他能看到一个很好的解决方案来解决我的问题的核心部分,并且慷慨提供来自 Perlmonks 的 Corian 并且不会像我第一次看到 @Pestilence 时那样被误导(无意冒犯 :))相信 Perl 无法完美地处理相关任务。事实上,Perl 完全有能力处理这种工作并且很容易做到。

以下代码是从可丽耐对我在 Perlmonks 上发布的问题的回答中粘贴的(逐字)。来源是here

#!/usr/bin/perl -w
package main;
use strict;
use DBI;
use Data::Dumper;

my $dbh = DBI->connect('dbi:WMI:');

my $sth = $dbh->prepare(<<WQL);
    SELECT * FROM __instanceoperationevent
    WITHIN 5
    WHERE TargetInstance ISA 'Win32_LogicalDisk'
    and TargetInstance.Name != 'C:'
WQL
$sth->execute();

# loops forever
while (defined (my $row = $sth->fetchrow_arrayref())) {
    my $ev = $row->[0];

    # Windows XP only :(
    print "Class\t",$ev->Path_->Class,"\n";
    for (qw(Name DeviceID Caption MediaType InterfaceType)) {
        print join "\t", $_, ($ev->TargetInstance->{$_} || '<none>');
        print "\n";
        if ($ev->Path_->Class eq '__InstanceCreationEvent') {
            print "Device (letter) $ev->{TargetInstance}->{Name} added\n";
        }
    }
}

所有的功劳都归可丽耐所有,我想把它做成 CW。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 2012-07-10
    • 2011-03-10
    • 1970-01-01
    相关资源
    最近更新 更多