我正在使用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";
Run Code Online (Sandbox Code Playgroud)
任何的想法?我想避免安装CPAN模块.它们在我们的服务器上安装起来非常困难.
如果我正在写这个,我会拆分目录字符串/并迭代每个部分.保持一堆碎片,一个..条目意味着"弹出",.意味着什么都不做,而其他任何东西都意味着将该字符串推入堆栈.完成后,只需将堆栈/作为分隔符加入.
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);
Run Code Online (Sandbox Code Playgroud)
如果你想保留主要..条目,你将不得不做这样的事情:
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));
Run Code Online (Sandbox Code Playgroud)