it-swarm-eu.dev

Převod relativní cesty na absolutní cestu bez symbolického propojení

Existuje příkaz Unix k získání absolutní (a kanonické) cesty z relativní cesty, která může obsahovat symbolické odkazy?

66
Benjamin

Můžete použít nástroj readlink s možností -f:

-f, --canonicalize

      canonicalize  by  following  every symlink in every component of
      the given name recursively; all  but  the  last  component  must
      exist

Některé distribuce, například ty, které používají GNU coreutils a FreeBSD , také přicházejí s obslužným programem realpath(1), který v podstatě pouze volá realpath(3) a do značné míry to samé.

83
Mat

Přenosná proměnná PWD je Shell nastavena na jedno absolutní umístění aktuálního adresáře. Jakákoli součást této cesty může být symbolickým odkazem.

case $f in
  /*) absolute=$f;;
  *) absolute=$PWD/$f;;
esac

Pokud chcete vyloučit také . A .., Přejděte do adresáře obsahujícího soubor a získejte tam $PWD:

if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}

Neexistuje žádný přenosný způsob, jak sledovat symbolické odkazy. Pokud máte cestu k adresáři, pak ve většině unices $(cd -- "$dir" && pwd -P 2>/dev/null || pwd) poskytuje cestu, která nepoužívá symbolické odkazy, protože shelly, které sledují symbolické odkazy, mají tendenci implementovat pwd -P („P“) pro „fyzické“).

Některé sektory poskytují nástroj pro tisk „fyzické“ cesty k souboru.

  • Rozumně novější systémy Linux (s GNU coreutils nebo BusyBox) mají readlink -f , stejně jako FreeBSD ≥ 8.3, NetBSD ≥4,0 a OpenBSD již v 2.2.
  • FreeBSD ≥4.3 má realpath (je také přítomen v některých systémech Linux a je v BusyBoxu).
  • Pokud je k dispozici Perl, můžete použít modul Cwd .

    Perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
    

Je pwd vhodný pro vaše potřeby? Poskytuje absolutní cestu k aktuálnímu adresáři. Nebo to, co chcete, je realpath () .

5
xanpeng

alister a rss67 in tento článek představuje nejstabilnější, kompatibilní a nejjednodušší způsob. Nikdy jsem neviděl lepší způsob než tohle.

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`

Pokud se chcete vrátit na původní místo,

ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH

nebo

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -

Přál bych si, aby to pomohlo. To bylo pro mě největší řešení.

3
Eonil

S ohledem na odpověď všech ostatních jsem zjistil, že níže uvedená funkce je velmi snadná a přenosná mezi linux/MAC OSX než ostatní, které jsem našla všude. Může někomu pomoci.

#!/usr/bin/bash
get_absolute_path(){
    file_path=`pwd $1`
    echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
0
lauksas

Ostatní odpovědi byly v pořádku, ale nebyly dostatečné pro mé potřeby. Potřeboval jsem řešení, které bych mohl použít ve svých skriptech na jakémkoli počítači. Mým řešením bylo napsat skript Shell, který mohu vyvolat ze skriptů, kde je potřebuji.

#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
  printf 'Usage: respath path [working-directory]\n' >&2
  exit 1
fi
cantGoUp=

path=$1
if [ $# -gt 1 ]; then
  cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks

#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
  printf '%s\n' "$path"
  exit 0
fi

#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
  case "$path" in
    ..*)
      if [ "$cwd" = '/' ]; then
        printf 'Invalid relative path\n' >&2
        exit 1
      fi
      if [ "$path" = '..' ]; then
        path=
      else
        path=`echo "$path" | sed 's;^\.\./;;'`
      fi
      cwd=`dirname $cwd`
      ;;
    *)
      break
      ;;
  esac
done

cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
  if [ -z "$cwd" ]; then
    cwd='/'
  fi
  printf '%s\n' "$cwd"
else
  printf '%s/%s\n' "$cwd" "$path"
fi

Toto řešení je psáno pro Bourne Shell pro přenositelnost. Mám to ve skriptu s názvem "respath.sh".

Tento skript lze použít takto:

respath.sh '/path/to/file'

Nebo takhle

respath.sh '/relative/path/here' '/path/to/resolve/relative/to'

Skript vyřeší cestu v prvním argumentu pomocí cesty z druhého argumentu jako výchozího bodu. Pokud je zadán pouze první argument, skript vyřeší cestu relativně k vašemu aktuálnímu pracovnímu adresáři.

0
Sildoreth

V případě, že navíc máte předdefinovanou cestu pro $1 (obvykle ${PWD}), bude fungovat následující:

CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
    case $1 in
        /*) echo "CWD=${CWD}"; ;;
        *) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
    esac
fi
0
Nikhil