1. 概要

このチュートリアルでは、bashで相対パスを拡張するさまざまな方法について学習します。

2. 絶対パスと相対パスの違い

Linuxでは、パスはディレクトリまたはファイルを参照するために使用されます。 ルートの最初のスラッシュ(/)とそれに続くスラッシュを区切り文字として使用して、ファイルシステムのルートから最終的な宛先までの完全なパスを指定します

/etc/ssl/certs
/usr/bin/ls
/usr/lib/libssl.so.3 

ただし、相対パスでは、パスをスラッシュではなくファイル名またはディレクトリ名で開始します。これは、現在のディレクトリからの相対パスであることを意味します。

file.txt
./file.txt
../../usr/bin/ls

例を挙げて、これをより明確に理解しましょう。 ディレクトリ/tmp / files にいて、file1というファイルを作成するとします。 これで、その特定のディレクトリ内のパスfile1または./file1 でファイルにアクセスできますが、他の場所からはアクセスできません。

$ cd /tmp/files/
$ touch file1
$ ls ./file1
./file1
$ cd /tmp/
$ ls ./file1
ls: ./file1: No such file or directory

相対パスを使用しているため、他のディレクトリからファイルにアクセスできません。 したがって、相対パスは現在のディレクトリに依存しますが、絶対パスを介してどこからでもファイルにアクセスできます。

シングルドットとダブルドットを使用して、それぞれ現在のディレクトリと親ディレクトリを参照します。 複数の二重ドットを使用して、ディレクトリ構造を上に移動し続けることができます。ホームディレクトリから / etc /passwdファイルへの相対パスを作成するとします。

$ pwd
/home/baeldung
$ cat ../../etc/passwd
root:x:0:0:root:/root:/bin/sh
...

2つの二重ドットで、 / home/baeldungから/に到達しました。

3. 相対パスの解決

絶対パスを必要とするプログラムに相対パスを渡すなど、さまざまな場合に相対パスを解決する必要がある場合があります。

3.1. Bashビルトインの使用

pwdなどの基本的なbash組み込み関数と目的の変数置換を活用するbash関数を作成できます。 これにより、外部プロセスを呼び出すオーバーヘッドが回避されます。

resolve_relative_path() (
    # If the path is a directory, we just need to 'cd' into it and print the new path.
    if [ -d "$1" ]; then
        cd "$1" || return 1
        pwd
    # If the path points to anything else, like a file or FIFO
    elif [ -e "$1" ]; then
        # Strip '/file' from '/dir/file'
        # We only change the directory if the name doesn't match for the cases where
        # we were passed something like 'file' without './'
        if [ ! "${1%/*}" = "$1" ]; then
            cd "${1%/*}" || return 1
        fi
        # Strip all leading slashes upto the filename
        echo "$(pwd)/${1##*/}"
    else
        return 1 # Failure, neither file nor directory exists.
    fi
)

関数を中括弧ではなく角かっこで囲んで、サブシェルで実行し、終了時に元の作業ディレクトリを復元する必要があります。

pwd はデフォルトではシンボリックリンクを解決しないため、 / tmp / symlinked_di rにいる場合、これは / tmp /original_dirへのシンボリックリンクです。の場合、pwd/tmp /symlinked_dirを出力します。 -P フラグを使用して、ディレクトリのシンボリックリンクを解決できます。 ただし、この関数はファイルのシンボリックリンクを解決しません。

いくつかの引数を使用してこの関数をテストしてみましょう。

$ pwd
/tmp/test
$ ls
directory  file1
$ resolve_relative_path file1
/tmp/test/file1
$ resolve_relative_path ..
/tmp
$ resolve_relative_path ../test/directory
/tmp/test/directory
$ resolve_relative_path /usr/lib/../bin/..
/usr

3.2. readlinkを使用する

readlinkコマンドを使用して、シンボリックリンクを含む相対パスを解決できます。 -fフラグを使用してフルパスを出力します

$ readlink -f /usr/../tmp/link
/tmp/real

ここで、/ tmp / link は、/ tmp / realファイルへのシンボリックリンクです。

readlink -f は、存在しないディレクトリで呼び出された場合にのみゼロ以外の終了コードを返しますが、ファイルのディレクトリが存在する場合はゼロを返します。 したがって、 readlink -f / tmp / non-existent は0を返しますが、はreadlink -f / non-existent-dir /non-existent-fileは1を返します。

3.3. realpathを使用する

最後に、 realpath コマンドがあります。これは、 readlink-fと同様に動作します。

$ realpath /tmp/non-existent; echo $?
/tmp/non-existent
0
$ realpath /non-existent-dir/non-existent-file; echo $?
realpath: /non-existent-dir: No such file or directory
1
$ realpath /tmp/link
/tmp/real

4. 結論

この記事では、絶対パスと相対パス、およびシンボリックリンクも考慮しながらbashスクリプトでそれらを拡張する方法について学習しました。