サイト内検索

2016/02/07(日)cutで後ろから数えたパス(名前)を取得したい

のむらです。
人から見るととてもしょーもないのでハマってしまったので備忘録。

Linuxのディストリビューション(やれUbuntuだのやれCentOSだのやれRedHat系だのというアレです)によっては使えるコマンドがあったりなかったりしますが、
普段shellでサクサクやっていくとあんまり気にならない、というか気にしなくなってきます。
今回はそのトラップに自らハマって抜け出すのに一日費やした話です。

いつものでアレなんですが、インフラエンジニア向けです。
そろそろ元々営業マンでしたとか、Webデザイナなんですがワタシとか言っても信じてもらえなくなりつつある今日この頃。

得意技はツールです><


【困ったこと】
特定のファイルのパスを切り出す際、どこまで深いか分からないが最後から2、3階層戻った場所にあるファイル・ディレクトリ名を取りたい。
ただし、このshellscriptファイルはどこからでも実行されるためフルパスで制御すること。
→実行する場所によっては..を取得してエラーになるため

【禁止事項】
yumとかrpmとか
awk(入ってない)
sed(嫌い)

【優先】
直感的なやつ


ユースケース
/ 直下
./ 直下
./root
./home/user
./(current)
./(current)/../
/(current)/../
./(current)/hoge/
/(current)/hoge/
./(current)/../fuga/
/(current)/../fuga/
`pwd`/.. (current)/
./(別のスクリプト)
    • call (current)
やっていたこと
readlink $0 | rev | cut -d'/' -f"$1"
今回のターニングポイントは$1です。
こいつの値はrevを使わないと$1=(Max'/' - $1)となるんですが、そもそもMax'/'を求めるのが大変煩わしい。
そこで、その辺を気にしないでrevでひっくり返して最後からN階層戻る場所を直撃すれば直感的にできるよね、という発想でした。
事実、これのおかげで引数だけを変えれば簡単に値を持ってこれたので満足していたわけですが。

代替案がこちら。
loop=$1
cd $(dirname $(readlink -f $0))

while [ "${loop}" -gt 0  ]
do
  cd ../
  loop=${loop}-1;
done

echo ${PWD##*/}
たかだかこんな事のために繰り返し文を持ってこなければならない、というのがイケてない…
乱暴な話をするなら、以下のコードでごまかすのは可能です。
[ "${loop}" -eq 1 ] && $(dirname $(readlink -f $0))
[ "${loop}" -eq 2 ] && $(dirname $(dirname $(readlink -f $0)))
[ "${loop}" -eq 3 ] && $(dirname $(dirname $(dirname $(readlink -f $0))))
...
while使うのと比べるとメンテナンス自体は簡単です。whileを使わずに書いただけとも言います。

cutの引数の最大値が明確に定まっていて、
後で仕様変更や運用ルールが変わらない事が担保されていて、
以降改修を実施する見込みがなければアリです。
OK キャンセル 確認 その他