メモの日々


2008年11月27日(木) [長年日記]

  • 腰が痛いのはもう治った。

[shell][unix][howto] シェルスクリプトファイル自身の格納ディレクトリの絶対パスを得る

毎回同じことを調べている。

#!/bin/sh
cd `dirname $0`
d=`pwd`
echo $d

で大体うまくいくが、パス中にシンボリックリンクがあったりファイル自身がシンボリックリンクだと、リンク先ファイルとは異なる絶対パスが得られてしまい困ることがある。格納ディレクトリからの相対パスで別のファイルを探したい時とか。

これを解決する簡単でポータブルな方法はなさそうだが、最近のLinuxだと readlink というコマンドがあるようで、これを使うと簡単に絶対パスを取得できた。

readlink は -f オプションを使うと

% ln -s /usr/bin/gcc link
% readlink -f link
/usr/bin/gcc
% readlink -f /usr/bin/gcc
/usr/bin/gcc

のようにリンクがあろうとなかろうと絶対パスを出力してくれるようなので、

#!/bin/sh
my_path=`readlink -f $0`
cd `dirname $my_path`
d=`pwd`
echo $d

のようにすればよさそう。

(追記)

今見ると上のスクリプトはおかしい。readlinkが絶対パスを出力してくれるならcdやpwdをする必要はなくて

#!/bin/sh
my_path=`readlink -f $0`
d=`dirname $my_path`
echo $d

でいいはず。

(追記2)

少なくともbashでは、スクリプト起動直後の $_ にコマンドの絶対パスが設定されていることを知った。

ただし、readlinkのようにシンボリックリンクを辿ってはくれない。また、$_ に絶対パスが設定されているのはスクリプトの起動直後だけだということに注意が必要。

$ cat myname.sh
#!/bin/bash
echo '  $_      :' $_
echo '  $0      :' $0
echo '  readlink:' `readlink -f $0`
echo aaa > /dev/null
echo '  $_      :' $_

$ ln -s myname.sh oreore.sh

$ ./myname.sh
  $_      : /home/kenichi/tmp/./myname.sh
  $0      : ./myname.sh
  readlink: /home/kenichi/tmp/myname.sh
  $_      : aaa

$ ./oreore.sh
  $_      : /home/kenichi/tmp/./oreore.sh
  $0      : ./oreore.sh
  readlink: /home/kenichi/tmp/myname.sh
  $_      : aaa

[shell][unix][howto] パイプの途中で行を追加する

パイプを使ってテキストを変換していくとき、途中で新しい行を追加したくなった。が、やり方をなかなか思いつかない。

awkのENDを使えばできた。

% echo "ore\nboku" | sort | awk '{print} END {print "omae"}'
boku
ore
omae

awk便利だな。awk使うならパイプ使わず全部awkで処理すればいいじゃない、それならperlでもいいじゃんか、という話になる。うーむ。

ところで、「man awk」だと英語のマニュアルが表示されるが「man gawk」とすると日本語訳(左はリンク切れ。こっちへ移行したみたい。)を読めることに気づいた。

[ruby] JRubyが実行できなかった

JRubyを使おうとここからダウンロードして展開したが、

% jruby
Exception in thread "main" java.lang.NoClassDefFoundError: org/jruby/Main
Caused by: java.lang.ClassNotFoundException: org.jruby.Main
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)

のようになり実行できなかった。

色々調べた結果、libディレクトリにあるべき jruby.jar というファイルが無いのが原因の模様。何故無いのか。

その原因は、おれのダウンロードしたファイルが jruby-src-1.1.5.tar.gz だったため。これだと、srcなので自分でビルドしないといけないみたい。jruby-bin-1.1.5.tar.gz というファイルをダウンロードし直したら、libに jruby.jar が存在し普通に実行できた。

配布ディレクトリにファイルが多すぎて、どれをダウンロードすればいいのかが分かりにくいのだ。気を付けろ。

やること

  • お香典
  • 洗顔
  • O2ケア
  • 5000円
本日のツッコミ(全2件) [ツッコミを入れる]
tito (2008年11月27日(木) 22:11)

行を追加ですが別解で<br>echo hoge | ( cat -; echo fuga )<br>の方が軽いと思います。

小川 (2008年11月28日(金) 01:58)

なるほど、このようにする方がよさそうです。ありがとうございます。<br>これはbashのマニュアルに「Compound Commands」として書かれている機能を使ったことになりそうですね。ちゃんと理解できていない気がするので、後でまた考えてみます。