17276


**質問背景**

[code]

    $(cd $(dirname $0)/.. && pwd)
    
[/code]

についてネット検索してみたら、

[code]

    $(cd $(dirname $0) && pwd)
    
[/code]

に関するページが見つかりました

**質問**

  * 両者の違いを教えてください
  * `/..` に特別な意味はある？

**最終的に知りたいこと**

[code]

    $(cd $(dirname $0)/.. && pwd)
    
[/code]

は、どういう意味でしょうか？ 多分、どのような環境でも動作するように設定していると思うのですが…


CC BY-SA 3.0
2015-10-05T11:33:21.747
17274
2015-10-05T13:12:38.697
2015-10-05T12:51:58.597
7886
question
bash sh
$(cd $(dirname $0)/.. && pwd) と $(cd $(dirname $0) && pwd) の違い


最初に質問に答えると次のようになります。

  * `$(cd $(dirname $0) && pwd)` ... 実行中のスクリプトがあるディレクトリの絶対パス (`/` で始まるパス) 文字列
  * `$(cd $(dirname $0)/.. && pwd)` ... 実行中のスクリプトがあるディレクトリの親ディレクトリの絶対パス文字列

ここで使われているシェル変数やコマンド、構文の意味は次のとおりです。

  * `$0` は実行中のスクリプトのパス (`bash` や `sh` に渡された引数そのもの) を表します。 
  * [`dirname`](http://pubs.opengroup.org/onlinepubs/009696799/utilities/dirname.html) は引数で与えたパス文字列のディレクトリ部分を返すコマンドです。
  * [`pwd`](http://pubs.opengroup.org/onlinepubs/009696799/utilities/pwd.html) はカレントディレクトリを絶対パスで返すコマンドです。
  * `$( ... )` はシェルで `...` を実行した結果 (標準出力) の文字列に置き換えられます。

一般に `$(cd DIR && pwd)` は、ディレクトリ `DIR` (相対パスを含む) の絶対パスを取得するためのポータブルな方法と考えられます。

実際に実行してみるのが理解が早いでしょう。次のようなファイル `script.sh` をいろんな場所に置いて実行してみてください。

[code]

    #!/bin/sh
    echo $0
    echo $(dirname $0)
    echo $(cd $(dirname $0) && pwd)
    echo $(cd $(dirname $0)/.. && pwd)
    
[/code]

`/tmp/script.sh` に置いて実行した場合は次のようになります。

[code]

    $ bash /tmp/script.sh 
    /tmp/script.sh
    /tmp
    /tmp
    /
    
[/code]

ポイントは bash にスクリプトとして相対パスを指定して実行したときです。

[code]

    $ cd /tmp
    $ bash script.sh 
    script.sh
    .
    /tmp
    /
    
[/code]

相対パスが渡されても `pwd` により絶対パスが得られていることがわかります。

また `pwd` はシェルが `$PWD`
で保持する「論理的な」カレントディレクトリを返します。次のようなシンボリックリンクを含むディレクトリに移動して実行してみるとそれがわかります。

[code]

    $ ln -s . /tmp/dir
    $ cd /tmp/dir/dir/dir/dir
    $ bash script.sh 
    script.sh
    .
    /tmp/dir/dir/dir/dir
    /tmp/dir/dir/dir
    
[/code]

`script.sh` の実体が置かれているディレクトリは `/tmp` ですが、 `pwd` は `cd` で移動した論理的なカレントディレクトリ
`/tmp/dir/dir/dir/dir` を返しています。シンボリックリンクの影響を排除した絶対パスを得るには `pwd -P` が使えます。

[code]

    $ cd /tmp/dir/dir/dir/dir
    $ pwd
    /tmp/dir/dir/dir/dir
    $ pwd -P
    /tmp
    
[/code]


CC BY-SA 3.0
2015-10-05T12:06:44.380
17276
2015-10-05T12:28:58.303
2015-10-05T12:28:58.303
9873
9873
17274
answer


質問の内容とは関係がありませんが、スクリプトファイルのパスにスペースやタブが含まれている場合を考慮しておいた方が良いかと思います。

[code]

    $ pwd
    /home/nemo
    
    $ mkdir $'foo bar'
    
    foo\ bar/a.sh:
    ==============
    #!/bin/bash
    echo $(cd $(dirname $0) && pwd)
    ==============
    
    $ ls foo\ bar/
    a.sh
    
    $ ./foo\ bar/a.sh
    /home/nemo
    
[/code]

となってしまいます。

これは、

[code]

    $ dirname ./foo bar/a.sh
    .
    bar
    
[/code]

となってしまうためです。なので、クォートしておいた方が無難かな、と思います。

[code]

    => echo $(cd "$(dirname "$0")" && pwd)
    
    $ foo\ bar/a.sh
    /home/nemo/foo bar
    
[/code]

さらに、パス名に改行コードが含まれている可能性も考慮する必要があるかもしれません(その場合は更に `$(cd ..)` 全体をクォートします)。


CC BY-SA 3.0
2015-10-05T13:12:38.697
17284
2015-10-05T13:12:38.697
17274
answer