MetaChrome
MetaChrome

Reputation: 3220

Get target name of hard link in bash (ie BASH_SOURCE)

#!/bin/bash
dir_self () {
    local source="${BASH_SOURCE[$1]}"
    while [ -h "$source" ]; do # resolve $source until the file is no longer a symlink
      dir="$( cd -P "$( dirname "$source" )" && pwd )"
      source="$(readlink "$source")"
      [[ $source != /* ]] && source="$dir/$source" # if $source was a relative symlink, we need to resolve it relative to the path where the symlink file was located
    done
    local dir="$( cd -P "$( dirname "$source" )" && pwd )"
    printf $dir
}
#source lib.bash,function,file, hard links return as link location, soft links as target
dir_self_file () {
    local num=2
    if [[ -n $1 ]];then
        num=3
    fi
    dir_self $num
}

I am using the above functions for determining the directory of a file that is sourcing a lib.bash containing said functions (not the directory of the executing file though that isn't relevant).

Considering the following directory structure:

ln_s->dir/ln_targ
ln_h->dir/ln_targ
dir/ln_targ
lib.bash

It is usable in the following way:

. $LIB_DIR/lib.bash
echo $(dir_self_file)

In ln_h it will echo the directory of ln_h while in ln_s it will echo the directory of dir/ln_targ.

In theory I would like to be able to get all relevant directories with regards to the context provided by this example, ie:

1) The directory of the sym link
2) The directory of the hard link
3) The directory of the target

As you can see though, the input to the dir_self provided by BASH_SOURCE specifies either one or the other.

Is there a way to retrieve all the specified values with bash?

Upvotes: 0

Views: 447

Answers (1)

chepner
chepner

Reputation: 531948

The mapping of a file name to the underlying inode on disk is a one-way mapping. Given an arbitrary inode, there is no way to discover all of the directory entries that point to it (i.e., what hard links for the file exist). That implies that, given your hard link ln_h, you cannot find from the file itself that another hard link dir/ln_targ exists. Each hard link to a file is on equal footing to the other; it is not the case that one is the 'real' name with the others being mere aliases.

(It is, however, possible to know how many hard links to a file exist. The file system tracks this information so that it knows when it is safe to reclaim the space used by a file which no longer has any hard links. This information is updated as new hard links are created and removed, however.)

Upvotes: 1

Related Questions