【Shell】実行時に指定した相対パスを絶対パスに変換する

■実装するプログラムの概要

shell実行時に指定する引数に相対パスを指定した場合、その相対パスを絶対パスに変換する。

※イメージ

$ ./sample.sh ./hoge/hoge.txt
/work/hoge/hoge.txt

■フローチャート

■プログラム仕様

インプット処理内容アウトプット
実行ファイル名をセットする。
【第1引数】
相対パス名
第1引数から指定した相対パスを変数に格納する。
【条件分岐】
▼引数あり
後続へ進む。
▼引数なし
エラーメッセージを出力する。
異常終了する。
【エラーメッセージ】
引数なし
【条件分岐】
▼指定したパスがディレクトリ、かつ、最後が「/」で終わっていない場合
末尾に「/」を追加する。
【条件分岐】
▼指定したパスが、ディレクトリ名とファイル名の場合
ディレクトリ名とファイル名を分けて変数に格納する。
後続へ進む。
▼ファイル名のみの場合
pwdコマンドでフルパス+ファイル名を出力する。
正常終了する。
【メッセージ】
絶対パス
【条件分岐】
▼変数に格納したディレクトリ名が存在する場合
後続へ進む。
▼変数に格納したディレクトリ名が存在しない場合
エラーメッセージを出力する。
異常終了する。
【エラーメッセージ】
ディレクトリなし
変数に格納したディレクトリ名へ移動し、カレントディレクトリのパスを変数に格納する。
【条件分岐】
▼カレントディレクトリがルートのみ「/」の場合
ディレクトリ変数を空文字に戻す。
絶対パスを出力する。【メッセージ】
絶対パス

■実行環境のディレクトリ階層構造

■サンプルコード

#!/bin/bash

# 実行モジュール名を取得(ファイル名のみ)
readonly MODULE_NAME=${0##*/}

# 指定した相対パスを変数に格納
file_path=$1

# 初期変数をセット
dir_name=
file_name=

# 引数を指定しているか確認(z:文字数が0かどうか)
if [[ -z ${file_path} ]]; then
    printf '%s\n' "${MODULE_NAME}:引数の文字に不備があります。" 1>&2
    exit 1
fi

# 指定したパスがディレクトリ、かつ、最後が「/」で終わっていない場合
# 末尾に「/」を追加する。
if [[ -d ${file_path} && ${file_path} != */ ]]; then
    file_path+=/
fi

# ディレクトリ名とファイル名を分ける
# ファイル名のみの場合は、pwdコマンドでフルパス指定し、終了する
# BASH_REMATCH[0]:マッチした結果
# BASH_REMATCH[1]:1つ目の()の結果「ディレクトリ名」
# BASH_REMATCH[2]:2つ目の()の結果「ファイル名」
if [[ ${file_path} =~ ^(.*/)(.*)$ ]]; then
    echo "---------- 参考 ----------"
    echo "BASH_REMATCH[0]:" ${BASH_REMATCH[0]}
    echo "BASH_REMATCH[1]:" ${BASH_REMATCH[1]}
    echo "BASH_REMATCH[2]:" ${BASH_REMATCH[2]}
    echo "-------------------------"
    dir_name=${BASH_REMATCH[1]}
    file_name=${BASH_REMATCH[2]}
else
    printf '%s\n' "${PWD}/${file_path}"
    exit 0
fi

# 変数「dir_name」が存在するディレクトリか調べる
if [[ ! -d ${dir_name} ]]; then
    printf '%s\n' "${MODULE_NAME}:ディレクトリ名に不備があります。" 1>&2
    exit 2
fi

# 変数「dir_name」に移動して「pwd」コマンドを実行
base_dir_name=$(cd -- "$dir_name" && pwd)

# 変数「base_dir_name」がルートのみ「/」の場合は、空文字に戻す
if [[ ${base_dir_name} == / ]]; then
    base_dir_name=
fi

# フルパスを出力
    printf '%s\n' "${base_dir_name}/${file_name}"

■実行結果

・相対パス「./hoge/hoge2.txt 」→絶対パス「/work/hoge/hoge2.txt」に変換

$ ./sample.sh ./hoge/hoge2.txt 
---------- 参考 ----------
BASH_REMATCH[0]: ./hoge/hoge2.txt
BASH_REMATCH[1]: ./hoge/
BASH_REMATCH[2]: hoge2.txt
-------------------------
/work/hoge/hoge2.txt

・相対パス「./nume/../tmp/hoge1.txt 」→絶対パス「/work/tmp/hoge1.txt」に変換

$ ./sample.sh ./nume/../tmp/hoge1.txt 
---------- 参考 ----------
BASH_REMATCH[0]: ./nume/../tmp/hoge1.txt
BASH_REMATCH[1]: ./nume/../tmp/
BASH_REMATCH[2]: hoge1.txt
-------------------------
/work/tmp/hoge1.txt

コメント