Convert Relative path to Absolute path, without changing directory to the file location.

Hello,

I am creating a file with all the source folders included in my git branch, when i grep for the used source, i found source included as relative path instead of absolute path, how can convert relative path to absolute path without changing directory to that folder and using readlink -f ?

grep -r "src +=" --include=*.spec $REPOROOT

src += ../src
src += ../stubs
src += ../../dataLU/src
src += ../../src   
src += ../src
src += ../export/src
src += ../src
src += ../src       
src += ../../src    
src += ../src  
grep -r "src +=" --include=*.spec $REPOROOT | cut -d "=" -f2

../src
../stubs
../../dataLU/src
../../src    
../src       
../export/src
../src
../src      
../../src   
../src  

i tried using the below two ways

echo "$(cd "$(dirname "../../dataLu/src")"; pwd)/$(basename "../../dataLu/src")"
readlink -f ../../dataLu/src

while this worked, i have to change directory to the location of the spec file there are more than 1000 spec files, hence i want to get the path from the top of the repo without changing directory

desired results are

a/src
b/src
x/y/dataLu/src

Thank you!

OS: linux SUSE (I don't have realpath)
Shell : bash

You need to include a variable which contains the full path of your source directory.

Is what you are asking?

In bash on some systems it is a shell function:

realpath ()                                                                                                                                                                                   
{                                                                                                                                                                                             
    f=$@;                                                                                                                                                                                     
    if [ -d "$f" ]; then                                                                                                                                                                      
        base="";                                                                                                                                                                              
        dir="$f";                                                                                                                                                                             
    else                                                                                                                                                                                      
        base="/$(basename "$f")";                                                                                                                                                             
        dir=$(dirname "$f");                                                                                                                                                                  
    fi;                                                                                                                                                                                       
    dir=$(cd "$dir" && /bin/pwd);                                                                                                                                                             
    echo "$dir$base"                                                                                                                                                                          
}        

I cannot vouch for this code because I use the standard C library realpath in a compiled module. The example above is a copy that I found a while back when researching a similar problem to what you have when trying to migrate scripts across Linux distros.

If someone knows more I'd like to see it.

1 Like

I don't think either of a/src , b/src , or x/y/dataLu/src is an absolute path; they all start downwards from your current working directory, $PWD .

Just in case neither the readlink nor the realpath solution please you, and you don't want external commands but bash builtins do the job for you, how would something along this line fit in:

DIR="../../dataLU/src"
TMP="${PWD%/*}${DIR#..}"
TMP="${TMP/*..*}"
ls "${TMP:-${PWD%/*/*}${DIR#../..}}"

Unfortunately, shell's "parameter expansion" only works on one variable at a time, so the repeated assignments to temporary variables are inevitable. Still it will be faster than creating a process plus loading and running any extermal command.

1 Like
#!/bin/bash

Spec=$( find . -name "*.spec" | sed 's/build.spec//g' )
hits=()
for each in ${Spec[@]}; do
  mhits=()

  hits=$( grep -rs "src +=" ${each}/build.spec | tr -d "(){}")
  for hit in ${hits[@]}; do   
    mhits="$mhits $( echo "${hit}" | cut -d "=" -f2 )"
  done
  for print in ${mhits[@]}; do
    if [[ "$print" == ..* ]]; then
      pushd $each > /dev/null
      fqn=$(readlink -f $print )
      opx=$( echo "${fqn}" | sed "s|${REPOROOT}|\$REPOROOT|g" )
      echo "$opx"
      popd > /dev/null
    fi
    if [[ "${print}" == *"REPOROOT"* ]]; then
      echo "$print"
    fi
  done
done

I wrote this one, and it worked