No Linux (que usa o GNU coreutils), readlink -f
faz o que você precisa.
Para sistemas derivados do BSD ou OS X, você pode precisar fazer mais algum trabalho. Consulte o link
Dado um único argumento arbitrário representando um arquivo (ou diretório, dispositivo, etc), como obtenho o caminho absoluto do argumento?
Eu já vi muitas respostas a essa pergunta envolvendo find / ls / stat / readlink e $ PWD, mas nenhuma que atenda a minha necessidade. Parece que a resposta mais próxima é o comando "whence" do ksh, mas eu preciso que ele funcione em sh / bash.
Suponha que um arquivo, foo.txt, esteja localizado em meu diretório inicial, /Users/matthew/foo.txt. Eu preciso do seguinte comportamento, apesar do meu diretório de trabalho atual (estou chamando o comando "abs"):
(PWD is ~)
$ abs foo.txt
/Users/matthew/foo.txt
$ abs ~/foo.txt
/Users/matthew/foo.txt
$ abs ./foo.txt
/Users/matthew/foo.txt
$ abs /Users/matthew/foo.txt
/Users/matthew/foo.txt
O que seria "abs" realmente?
TIA, Mateus
No Linux (que usa o GNU coreutils), readlink -f
faz o que você precisa.
Para sistemas derivados do BSD ou OS X, você pode precisar fazer mais algum trabalho. Consulte o link
Aqui está um script perl que escrevi anos atrás e que faz exatamente isso. Ele persegue links simbólicos para obter o caminho "canônico":
#!/usr/bin/perl -w
use diagnostics;
require Cwd;
$CMD = $0;
$CMD =~ s,^.*/,,;
sub err {
print STDERR "\n",@_,"\n" if (scalar(@_));
exit(1);
}
sub warning {
print STDERR "\n",@_,"\n" if (scalar(@_));
}
sub syntax {
print STDERR @_,"\n" if (scalar(@_));
print STDERR "Use -h for help.\n";
exit(1);
}
sub help {
print(join("\n",
("Usage: $CMD [OPTIONS] file file ..",
" $CMD prints the 'real' path for each file by expanding all",
" symbolic links and resolving references to '.', '..' and",
" extra '/' characters. The resulting path will have no symbolic",
" link, '.' or '..' components.",
"Options:",
" -h // print this message",
" -v // show process of resolving file",
"")));
}
sub abspath {
my $path = shift(@_);
return ( ($path =~ m,^/,)
? $path
: ( (($#_ > -1) ? shift(@_) : Cwd::getcwd()) . "/" . $path )
);
}
sub realpath {
my $left_path = abspath(@_);
my @left;
my @right;
my @link;
my $link;
my $upcount = 0;
@right = ();
@left = split("/",$left_path);
shift(@left) if $#left;
while(@left) {
$left_path = "/" . join("/",@left);
printf("test: %s ## %s\n",$left_path,join("/",@right)) if $verbose;
if($left[$#left] eq "..") {
$upcount++;
pop(@left);
}
elsif($left[$#left] eq "." || $left[$#left] eq "") {
# a "/./" or a "//"
pop(@left);
}
elsif ($upcount) {
return undef unless $#left >= $upcount - 1;
$#left -= $upcount;
$upcount = 0;
}
else {
return undef unless ( -e $left_path );
if ( $link = readlink($left_path) ) {
printf(" : %s --> %s\n",$left_path,$link) if $verbose;
@link = split("/",$link);
if ($link[0] eq "") {
@left = @link;
shift(@left);
} else {
pop(@left);
push(@left,@link);
}
} else {
unshift(@right,pop(@left));
}
}
}
printf("done: /%s\n",join("/",@right)) if $verbose;
return("/" . join("/",@right));
}
$verbose = 0;
@files = ();
while ($arg = shift(@ARGV)) {
if ($arg eq "-h") {
help();
exit(9);
} elsif ($arg eq "-v") {
$verbose = 1;
} elsif ($arg eq "--") {
last;
} elsif ($arg =~ m/^-/) {
syntax("Unknown option: '$arg'");
} else {
unshift(@ARGV,$arg);
last;
}
}
@files = @ARGV;
@ARGV = ();
my $err = 0;
my $f;
my $p;
foreach $f (@files) {
print "\n" if $verbose;
$p = realpath($f);
if(defined($p)) {
print("$p\n");
}
else {
warning("$f: no such file\n");
$err++;
}
}
exit($err);