清理目录名称(从目录名称中删除“..”和“。”)

时间:2010-11-17 15:37:54

标签: perl

我正在使用Java类编写SFTP模块(是的。我知道这很愚蠢。是的,我知道Net :: SFTP。这是政治上我们必须这样做的原因。)

底层Java程序基本上有几个类来从服务器获取,放置,列出和删除文件。在这些调用中,您必须为其提供目录和文件。无法移出原始目录。你自己坚持做跟踪。

我决定如果跟踪你的远程目录会很好,并创建了一个Chdir方法来跟踪你所在的目录,从FTP的根目录开始。我所做的就是将目录存储在属性中,并在其他命令中使用它。很简单,也很有效。

问题是存储的目录名称越来越长。例如,如果目录是foo/bar/barfoo,而您$ftp->Chdir("../.."),则新目录将是foo/bar/barfoo/../..而不是foo。两者在技术上都是正确的,但第一个更清晰,更容易理解。

我想要一些能够简化目录名称的代码。我考虑使用File::Spec::canonpath,但具体说明这样做。它指的是Cwd,但这取决于对机器的直接访问,我通过FTP连接。

我已经提出了以下代码片段,但它确实缺乏优雅。它应该更简单,更明显它在做什么:

use strict;
use warnings;

my $directory = "../foo/./bar/./bar/../foo/barbar/foo/barfoo/../../fubar/barfoo/..";

print "Directory = $directory\n";
$directory =~ s{(^|[^.])\.\/}{$1}g;
print "Directory = $directory\n";
while ($directory =~ s{[^/]+/\.\.(/|$)}{}) {
    print "Directory = $directory\n";
}
$directory =~ s{/$}{};
print "Directory = $directory\n";

有什么想法吗?我想避免安装CPAN模块。它们在我们的服务器上安装起来非常困难。

4 个答案:

答案 0 :(得分:6)

如果我写这篇文章,我会将目录字符串拆分为/并迭代每一段。保持一堆片段,..条目意味着“pop”,.意味着什么都不做,而其他任何东西都意味着将该字符串推入堆栈。完成后,只需使用/作为分隔符加入堆栈。

my @parts = ();
foreach my $part (File::Spec->splitdir($directory)) {
    if ($part eq '..') {
        # Note that if there are no directory parts, this will effectively
        # swallow any excess ".." components.
        pop(@parts);
    } elsif ($part ne '.') {
        push(@parts, $part);
    }
}

my $simplifiedDirectory = (@parts == 0) ? '.' : File::Spec->catdir(@parts);

如果你想保留领先的..条目,你将不得不这样做:

my @parts = ();
my @leadingdots = ();

foreach my $part (File::Spec->splitdir($directory)) {
    if ($part eq '..') {
        if (@parts == 0) {
            push(@leadingdots, '..');
        } else {
            pop(@parts);
        }
    } elsif ($part ne '.') {
        push(@parts, $part);
    }
}

my $simplifiedDirectory = File::Spec->catdir((@leadingdots, @parts));

答案 1 :(得分:2)

我在CPAN上有一个纯粹的Perl模块用于修剪路径:Path::Trim。从您的工作目录下载,复制和使用它。应该很容易。

答案 2 :(得分:1)

我不确定您是否可以访问该目录。

如果可以,您可以转到该目录并在那里getcwd执行:

my $temp = getcwd;          # save the current directory
system ("cd $directory");   # change to $directory
$directory = getcwd;        
system ("cd $temp");        # switch back to the original directory

答案 3 :(得分:0)

SFTP协议支持执行您想要的实际路径命令。