Pregunta

I have two values:

  • a current directory name
  • an absolute or relative file name

I need to construct an unambiguous absolute filename (starting with / and without any ../ and without ./) which corresponds to accessing this file while the directory is the current directory.

I need to do this in Perl in Unix.

I've tried use File::Path; but this does not work right (bug?):

perl -MPath::Class -e 'my $fileObj = Path::Class::File->new("/boot", "/xx"); 
                       print $fileObj->absolute, "\n";'

Output:

/boot/xx

But it should print /xx because it is an absolute path, and it should not depend on the current directory!

¿Fue útil?

Solución 2

# ("/base/path", "x") -> "/base/path/x"
# ("/base/path", "../x") -> "/base/x"
# ("/base/path", "/x") -> "/x"
sub AbsoluteNormalizedPath {
  my ($dir, $filename) = @_;
  $filename = "$dir/$filename" unless $filename =~ m{^/};
  my @components = split m{/+}, $filename;
  shift @components; # Первый компонент всегда - пустая строка, вырезаем его
  # Компоненты без ".." и ".". Работает как стек: добавляем обычные компоненты, убираем последние компонент на "..", игнорируем ".":
  my @normalizedComponents;
  foreach my $component (@components) {
    next if $component eq '.';
    if($component eq '..') {
      # В Unix parent директория корневой директории - сама корневая директория, то есть /.. - то же самое, что /
      # Так что, если список пустой - это не ошибка, оставляем его пустым (что соответсвует корневой директории).
      pop @normalizedComponents if @normalizedComponents;
    } else {
      push @normalizedComponents, $component;
    }
  }
  return '/' . join('/', @normalizedComponents);
}

Otros consejos

Path::Class use the whole path to determine if a file is absolute or relative so in the example it is: "/boot/xx". the outputted string. To solve your problem you need something like this:

use Path::Class

my $fileObj = Path::Class::File->new("/xx");

$fileObj = Path::Class::File->new("/boot",$fileObj->relative()) if $fileObj->is_relative();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top