代码之家  ›  专栏  ›  技术社区  ›  David W.

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

  •  3
  • David W.  · 技术社区  · 14 年前

    我正在使用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 回复  |  直到 14 年前
        1
  •  6
  •   cdhowie    14 年前

    如果我写这个,我会把目录字符串 / 在每一个片段上迭代。维护一堆碎片 .. 入口意味着“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));
    
        2
  •  2
  •   Alan Haggai Alavi    14 年前

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

        3
  •  1
  •   Aakash Goel    14 年前

    我不确定你是否能进入那个目录。

    如果可以的话,你可以去那个目录做一个 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
    
        4
  •  0
  •   salva    14 年前

    SFTP协议支持realpath命令,这正是您想要的。