简体   繁体   中英

How to convert “..” in path names to absolute name in a bash script?

How to convert the .. in the path names to absolute path names in a bash script. That is, if I have a path /home/nohsib/dvc/../bop , I want this to be changed to the path without dots in it, in this case /home/nohsib/bop

How can I do that?

What you're looking for is readlink :

absolute_path=$(readlink -m /home/nohsib/dvc/../bop)

Please note: You need to use GNU's readlink implementation which offers the "-m" option. BSD's readlink for example does not.

Try:

ABSOLUTE_PATH=$(cd /home/nohsib/dvc/../bop; pwd)

One issue with using:

ABSOLUTE_PATH=$(cd ${possibleDirectory}; pwd)

is that if ${possibleDirectory} doesn't exist, ABSOLUTE_PATH will then be set to the current directory. Which is probably NOT what you want or expect.

I think using this version may be more desirable in general:

ABSOLUTE_PATH=$(cd ${possibleDirectory} && pwd)

If ${possibleDirectory} does not exist or is not accessible, due to missing directory access permissions, ABSOLUTE_PATH will contain the empty string.

The advantage of this is that you can then test for the empty string or let it fail naturally, depending on the circumstances. Defaulting to the current directory in the case of a failed 'cd' command may lead to very unexpected and possibly disastrous results (eg rm -rf "$ABSOLUTE_PATH" )

If you want to do it without following any symlinks, then try using realpath with option -s :

$ realpath -s /home/nohsib/dvc/../bop
/home/nohsib/bop

Note that with realpath , normally all but the last component must exist. So for the above to work, the following must all be present in the file system:

/home
/home/nohsib
/home/nohsib/dvc

But you can bypass that requirement using the -m option.

$ realpath -sm /home/nohsib/dvc/../bop
/home/nohsib/bop

(Note realpath is not available on all systems, especially older non-Debian systems. For those working on embedded Linux, unfortunately Busybox realpath doesn't support the -s or -m switches.)

Use

echo Absolute path: $(cd $1; pwd)

Relative paths must be converted into absolute, it is NOT required to exist!

Neither symlinks should be resolved.

Try this one-line python solution:

abs_path=$(python -c "import os; print(os.path.abspath(\"$rel_path\"))")  

in your example:

python -c "import os; print(os.path.abspath(\"/home/nohsib/dvc/../bop\"))"  

returns /home/nohsib/bop

Just an additional note, if your current path is under a symlink, you can resolve the true path with this:

pwd -P

To solve your specific problem, this will issue a cd command to change directory to the path without the '..' in it. Note you will be in the same folder, just with the correct path:

cd `pwd -P`

As an alternative to GNU's readlink and realpath, I had created functions as well that would run in scripts independent of external commands like pwd and stuffs.

http://www.linuxquestions.org/questions/blog/konsolebox-210384/getting-absolute-paths-of-unix-directories-and-filenames-in-shell-scripts-3956/

One of those is this one. It will save the absolute path to $__. I used read there to be safe from pathname expansion.

function getabspath {
    local -a T1 T2
    local -i I=0
    local IFS=/ A

    case "$1" in
    /*)
        read -r -a T1 <<< "$1"
        ;;
    *)
        read -r -a T1 <<< "/$PWD/$1"
        ;;
    esac

    T2=()

    for A in "${T1[@]}"; do
        case "$A" in
        ..)
            [[ I -ne 0 ]] && unset T2\[--I\]
            continue
            ;;
        .|'')
            continue
            ;;
        esac

        T2[I++]=$A
    done

    case "$1" in
    */)
        [[ I -ne 0 ]] && __="/${T2[*]}/" || __=/
        ;;
    *)
        [[ I -ne 0 ]] && __="/${T2[*]}" || __=/.
        ;;
    esac
}

one good solution under a shell would be:

readlink -ev mypathname

It prints out the full path name with dots resolved.

Try this (assuming your relative path is stored in the variable $rel_path):

echo "`cd $rel_path; pwd`"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM