You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否优化这款用于查找系统所有Perl安装的命令行Perl脚本?

Perl脚本优化:修复Cygwin显示异常并增强稳定性

问题背景

原脚本用于扫描系统$PATH环境变量中的所有Perl安装实例,输出包含Perl版本、文件大小、安装路径及MD5校验和等信息,但在Cygwin系统上存在显示异常问题,以下是修复并优化后的版本。

优化后的脚本

#!/usr/bin/env perl
# Last modified: Sat Aug 24 2024 10:48:44 PM -04:00 [EDT]
# 优化版本:修复Cygwin兼容性,增强错误处理与格式化稳定性
use strict;
use warnings;
use File::Which;
use File::Basename;
use File::stat;
use Digest::MD5;

=head1 安装

`chmod 700 perlwitch` - 在GNU/Linux及类Unix系统执行

=head1 使用

`perl perlwitch`

=cut

# 获取所有Perl可执行文件
my @heap = which('perl');

# 过滤非Windows/Cygwin下的.exe文件(仅针对Windows/Cygwin环境)
if ($^O =~ /^(cygwin|MSWin32)$/) {
    @heap = grep { /\.exe$/i } @heap;
}

my @versions;
my $max_path_len = 0;

# 预处理:获取每个Perl的版本并计算最长路径长度
foreach my $perl_path (@heap) {
    $max_path_len = length($perl_path) if length($perl_path) > $max_path_len;
    
    # 安全打开管道获取版本信息,修正优先级问题
    open my $read_pipe, '-|', $perl_path, '-v' 
        or do {
            warn "无法执行 $perl_path 获取版本信息: $!\n";
            push @versions, '未知版本';
            next;
        };
    
    my $version = '未知版本';
    while (<$read_pipe>) {
        # 修正正则表达式,准确匹配Perl版本格式(如v5.36.3)
        if (/This is perl .+(v\d+\.\d+\.\d+)\)/) {
            $version = $1;
            last; # 匹配到后立即退出循环,提升效率
        }
    }
    close $read_pipe or warn "关闭管道时出错: $?\n";
    push @versions, $version;
}

# 计算格式化参数,避免负数长度
my $path_fmt_len = $max_path_len + 6;
my $dir_fmt_len = $max_path_len > 4 ? $max_path_len - 4 : 10; # 最小保留10位宽度

# 输出表头
printf "%-${path_fmt_len}s %-10s %10s %-${dir_fmt_len}s %s\n", 
    'Perl路径', '版本', '文件大小', '安装目录', 'MD5校验和';
print '-' x ($path_fmt_len + 10 + 12 + $dir_fmt_len + 33), "\n";

# 遍历输出每个Perl实例信息
for my $index (0..$#heap) {
    my $perl_path = $heap[$index];
    my $version = $versions[$index];
    
    # 获取文件大小
    my $st = stat($perl_path);
    my $file_size = $st ? $st->size : '无法获取';
    
    # 获取安装目录
    my (undef, $install_dir, undef) = fileparse($perl_path);
    
    # 计算MD5校验和
    my $md5_sum = csum($perl_path);
    
    # 格式化输出,确保对齐
    printf "%-${path_fmt_len}s %-10s %10s %-${dir_fmt_len}s %s\n", 
        $perl_path, $version, $file_size, $install_dir, $md5_sum;
}

# MD5校验和计算子函数
sub csum {
    my $fpath = shift;
    open my $fh, '<', $fpath 
        or do {
            warn "无法打开文件 $fpath: $!\n";
            return '计算失败';
        };
    binmode $fh;
    my $checksum = Digest::MD5->new->addfile($fh)->hexdigest;
    close $fh;
    return $checksum;
}

__END__

=pod

本程序用于定位系统`$PATH`环境变量中所有可找到的Perl安装实例,适合在久未使用或不熟悉的系统上快速梳理Perl环境。
输出包含MD5校验和,可轻松识别重复实例(例如通过符号链接指向同一文件的情况,如Debian系统中/bin链接到/usr/bin)。

=head3 复杂场景示例输出(Cygwin与Windows Perl共存)

    Perl路径                          版本        文件大小 安装目录          MD5校验和
    -------------------------------------------------------------------------------------------
    C:\ix\cygwin\bin\perl.EXE         v5.36.3       12819 C:\ix\cygwin\bin\ 68ba8b0c3d9bb4859076e938e0cbdafe
    C:\perl\perl\bin\perl.EXE         v5.32.1       39936 C:\perl\perl\bin\ 3686d8a7e98b82a6452f88fef293ca1a

=head2 许可证

Copyright (c) 2024 Soren Andersen. All rights reserved.

本库为自由软件;可依据与Perl相同的条款重新发布和修改。

=cut

核心优化点

  • 修复Cygwin兼容性:
    • 替换原脚本中易出错的splice过滤逻辑,改用grep安全过滤.exe文件,避免索引混乱
    • 确保路径解析与文件状态获取在Cygwin混合路径环境下正常工作
  • 增强版本匹配准确性:修正正则表达式,准确匹配vX.X.X格式的Perl版本,避免匹配失败
  • 优化错误处理:
    • 修正管道打开的优先级问题(用or替代||),确保错误提示准确触发
    • 对文件打开、版本获取等环节添加容错处理,避免脚本中途崩溃
  • 稳定格式化输出:
    • 处理路径长度过短的情况,避免$strl-4产生负数导致格式化报错
    • 添加表头与分隔线,提升输出可读性
  • 代码规范:开启strict模式,所有变量添加my声明,提升代码可维护性

内容的提问来源于stack exchange,提问作者amphibole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 09:22:04