webentwicklung-frage-antwort-db.com.de

Erweitern Sie einen möglichen relativen Pfad in Bash

Als Argumente für mein Skript gibt es einige Dateipfade. Diese können natürlich relativ sein (oder ~ enthalten). Aber für die Funktionen, die ich geschrieben habe, brauche ich Pfade, die absolut sind, aber ihre Symlinks nicht aufgelöst haben.

Gibt es dafür eine Funktion?

56
laar

MY_PATH=$(readlink -f $YOUR_ARG) löst relative Pfade wie "./" und "../" auf

Betrachten Sie dies auch ( source ):

#!/bin/bash
dir_resolve()
{
cd "$1" 2>/dev/null || return $?  # cd to desired directory; if fail, quell any error messages but return exit status
echo "`pwd -P`" # output full, link-resolved path
}

# sample usage
if abs_path="`dir_resolve \"$1\"`"
then
echo "$1 resolves to $abs_path"
echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected
else
echo "Could not reach $1"
fi
53
Amir Afghani

http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-und-dateiname-680368/page3.html hat Folgendes

function abspath {
    if [[ -d "$1" ]]
    then
        pushd "$1" >/dev/null
        pwd
        popd >/dev/null
    Elif [[ -e $1 ]]
    then
        pushd "$(dirname "$1")" >/dev/null
        echo "$(pwd)/$(basename "$1")"
        popd >/dev/null
    else
        echo "$1" does not exist! >&2
        return 127
    fi
}

welche pushd/popd verwendet, um in einen Zustand zu gelangen, in dem pwd nützlich ist.

34
Mike Samuel

Einfaches Liner:

function abs_path {
  (cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}

Verwendungszweck:

function do_something {
    local file=$(abs_path $1)
    printf "Absolute path to %s: %s\n" "$1" "$file"
}
do_something $HOME/path/to/some\ where

Ich versuche immer noch herauszufinden, wie ich dafür sorgen kann, dass der Pfad überhaupt nicht beachtet wird (ob er vorhanden ist oder nicht) (er kann auch beim Erstellen von Dateien verwendet werden).

14
andsens

Dies macht den Trick für mich unter OS X: $(cd SOME_DIRECTORY 2> /dev/null && pwd -P)

Es sollte überall funktionieren. Die anderen Lösungen schienen zu kompliziert zu sein.

7
Mike Pulaski

unter OS X können Sie verwenden

stat -f "%N" YOUR_PATH

unter Linux können Sie realpath ausführbar sein. Wenn nicht, kann Folgendes funktionieren (nicht nur für Links):

readlink -c YOUR_PATH
5
Vitaly Kushner

Vielleicht ist dies besser lesbar und verwendet keine Subshell und ändert das aktuelle Verzeichnis nicht:

dir_resolve() {
  local dir=`dirname "$1"`
  local file=`basename "$1"`
  pushd "$dir" &>/dev/null || return $? # On error, return error code
  echo "`pwd -P`/$file" # output full, link-resolved path with filename
  popd &> /dev/null
}
1
sja

Verwenden Sie readlink -f <relative-path>, z.

export FULLPATH=`readlink -f ./`
0
isapir

Es gibt noch eine andere Methode. Sie können die Einbettung von python in ein Bash-Skript verwenden, um einen relativen Pfad aufzulösen.

abs_path=$(python3 - <<END
from pathlib import Path
path = str(Path("$1").expanduser().resolve())
print(path)
END
)
0
cy8g3n

selbstbearbeitung, ich habe gerade bemerkt, dass das OP sagte, er suche nicht nach aufgelösten Symlinks:

"Aber für die Funktionen, die ich geschrieben habe, brauche ich absolute Pfade, deren Symlinks jedoch nicht aufgelöst werden."

Also denke, das ist doch nicht so gut für seine Frage. :)

Da ich im Laufe der Jahre viele Male darauf gestoßen bin und diesmal eine reine bash portable Version brauchte, die ich unter OSX und Linux verwenden konnte, schrieb ich eine und schrieb eine:

Die lebende Version lebt hier:

https://github.com/keen99/Shell-functions/tree/master/resolve_path

aber um der Sache willen, hier ist die aktuelle Version (ich denke, es ist gut getestet ... aber ich bin offen für Rückmeldungen!)

Es könnte nicht schwer sein, es mit normaler Borne-Shell (sh) zum Laufen zu bringen, aber ich habe es nicht versucht ... Ich mag $ FUNCNAME zu sehr. :)

#!/bin/bash

resolve_path() {
    #I'm bash only, please!
    # usage:  resolve_path <a file or directory> 
    # follows symlinks and relative paths, returns a full real path
    #
    local owd="$PWD"
    #echo "$FUNCNAME for $1" >&2
    local opath="$1"
    local npath=""
    local obase=$(basename "$opath")
    local odir=$(dirname "$opath")
    if [[ -L "$opath" ]]
    then
    #it's a link.
    #file or directory, we want to cd into it's dir
        cd $odir
    #then extract where the link points.
        npath=$(readlink "$obase")
        #have to -L BEFORE we -f, because -f includes -L :(
        if [[ -L $npath ]]
         then
        #the link points to another symlink, so go follow that.
            resolve_path "$npath"
            #and finish out early, we're done.
            return $?
            #done
        Elif [[ -f $npath ]]
        #the link points to a file.
         then
            #get the dir for the new file
            nbase=$(basename $npath)
            npath=$(dirname $npath)
            cd "$npath"
            ndir=$(pwd -P)
            retval=0
            #done
        Elif [[ -d $npath ]]
         then
        #the link points to a directory.
            cd "$npath"
            ndir=$(pwd -P)
            retval=0
            #done
        else
            echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2
            echo "opath [[ $opath ]]" >&2
            echo "npath [[ $npath ]]" >&2
            return 1
        fi
    else
        if ! [[ -e "$opath" ]]
         then
            echo "$FUNCNAME: $opath: No such file or directory" >&2
            return 1
            #and break early
        Elif [[ -d "$opath" ]]
         then 
            cd "$opath"
            ndir=$(pwd -P)
            retval=0
            #done
        Elif [[ -f "$opath" ]]
         then
            cd $odir
            ndir=$(pwd -P)
            nbase=$(basename "$opath")
            retval=0
            #done
        else
            echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2
            echo "opath [[ $opath ]]" >&2
            return 1
        fi
    fi
    #now assemble our output
    echo -n "$ndir"
    if [[ "x${nbase:=}" != "x" ]]
     then
        echo "/$nbase"
    else 
        echo
    fi
    #now return to where we were
    cd "$owd"
    return $retval
}

hier ist ein klassisches Beispiel dank Brew:

%% ls -l `which mvn`
lrwxr-xr-x  1 draistrick  502  29 Dec 17 10:50 /usr/local/bin/[email protected] -> ../Cellar/maven/3.2.3/bin/mvn

verwenden Sie diese Funktion und es wird der -real-Pfad zurückgegeben:

%% cat test.sh
#!/bin/bash
. resolve_path.inc
echo
echo "relative symlinked path:"
which mvn
echo
echo "and the real path:"
resolve_path `which mvn`


%% test.sh

relative symlinked path:
/usr/local/bin/mvn

and the real path:
/usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
0
keen