Skip to main content
added 581 characters in body
Source Link
Stéphane Chazelas
  • 586.8k
  • 96
  • 1.1k
  • 1.7k

The bash shell does not have a built-in way to explicitly get thean absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -r -- $pathname:P

and get /home/kk/.zshenv back (note that it also resolves all symbolic links wherever possible is a similar way as realpath() would).

In bash, you could, for a pathname designating a non-directory and assuming you have search access to its parent directory, use

$ pathname=../../home/kk/.zshenv
$ ( OLDPWD=- CDPATH= cd -P -- "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname. The -P is needed to avoid cd's special treatment of .. components. It has the side effect of resolving symlinks components in the directory itself. If the file itself is a symlink however, it won't be resolved (that's a difference from zsh's :P modifier).

We set OLDPWD to - to work around the fact that cd -P -- - does a chdir($OLDPWD) instead of chdir("-") (that trick works in bash but not all other sh implementations).

For a directory path it's easier:

$ pathname=../../home/kk
$ ( OLDPWD=- CDPATH= cd "$pathname"-P &&-- printf"$pathname" '%s\n'&& "$PWD"pwd )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        OLDPWD=- CDPATH= cd "$1"-P &&-- printf"$1" '%s\n'&& "$PWD"pwd
    else
        OLDPWD=- CDPATH= cd -P -- "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

UsingDepending on the OS, using the function with no argument will return the absolute path of the current directory or give an error.

To resolve symbolic links in the reply from the function, use In future versions of cd -Pbash in place of just, that's likely to be an error on every system, as cd '' to fail will become a POSIX requirement.

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname:P

and get /home/kk/.zshenv back.

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

The bash shell does not have a built-in way to explicitly get an absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -r -- $pathname:P

and get /home/kk/.zshenv back (note that it also resolves all symbolic links wherever possible is a similar way as realpath() would).

In bash, you could, for a pathname designating a non-directory and assuming you have search access to its parent directory, use

$ pathname=../../home/kk/.zshenv
$ ( OLDPWD=- CDPATH= cd -P -- "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname. The -P is needed to avoid cd's special treatment of .. components. It has the side effect of resolving symlinks components in the directory itself. If the file itself is a symlink however, it won't be resolved (that's a difference from zsh's :P modifier).

We set OLDPWD to - to work around the fact that cd -P -- - does a chdir($OLDPWD) instead of chdir("-") (that trick works in bash but not all other sh implementations).

For a directory path it's easier:

$ pathname=../../home/kk
$ ( OLDPWD=- CDPATH= cd -P -- "$pathname" && pwd )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        OLDPWD=- CDPATH= cd -P -- "$1" && pwd
    else
        OLDPWD=- CDPATH= cd -P -- "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Depending on the OS, using the function with no argument will return the absolute path of the current directory or give an error. In future versions of bash, that's likely to be an error on every system, as cd '' to fail will become a POSIX requirement.

deleted 2 characters in body
Source Link
Kusalananda
  • 356.2k
  • 42
  • 737
  • 1.1k

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname(:P)

and get /home/kk/.zshenv back.

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname(:P)

and get /home/kk/.zshenv back.

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname:P

and get /home/kk/.zshenv back.

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

deleted 149 characters in body
Source Link
Kusalananda
  • 356.2k
  • 42
  • 737
  • 1.1k

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname(:aP)

and get /home/kk/.zshenv back. Using (:A) in place of (:a) would additionally resolve any symbolic links in the result (if the system has the realpath(3) library function).

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname(:a)

and get /home/kk/.zshenv back. Using (:A) in place of (:a) would additionally resolve any symbolic links in the result (if the system has the realpath(3) library function).

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

The bash shell does not have a built-in way to explicitly get the absolute path given a relative pathname.

In the zsh shell, one could do

pathname=../../home/kk/.zshenv
print -- $pathname(:P)

and get /home/kk/.zshenv back.

In bash, you could, for a pathname designating a non-directory, use

$ pathname=../../home/kk/.zshenv
$ ( cd "${pathname%/*}" && printf '%s/%s\n' "$PWD" "${pathname##*/}" )
/home/kk/.zshenv

That is, temporarily (in a sub-shell) cd to the directory holding the file, and then construct the absolute pathname using the value $PWD and the filename component of the pathname.

For a directory path it's easier:

$ pathname=../../home/kk
$ ( cd "$pathname" && printf '%s\n' "$PWD" )
/home/kk

This could obviously be put into a shell function for convenience:

myrealpath () (
    if [[ -d $1 ]]; then
        cd "$1" && printf '%s\n' "$PWD"
    else
        cd "${1%/*}" && printf '%s/%s\n' "$PWD" "${1##*/}"
    fi
)

(Note that this whole function is defined in a sub-shell to avoid changing the working directory for the calling shell.)

Testing this function:

$ myrealpath ../../home/kk
/home/kk
$ myrealpath ../../home/kk/.zshenv
/home/kk/.zshenv

Using the function with no argument will return the absolute path of the current directory.

To resolve symbolic links in the reply from the function, use cd -P in place of just cd.

added 34 characters in body
Source Link
Kusalananda
  • 356.2k
  • 42
  • 737
  • 1.1k
Loading
added 94 characters in body
Source Link
Kusalananda
  • 356.2k
  • 42
  • 737
  • 1.1k
Loading
Source Link
Kusalananda
  • 356.2k
  • 42
  • 737
  • 1.1k
Loading