13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

パイプで渡したパスに無理やりcdするシェルスクリプト

Last updated at Posted at 2015-02-09

パイプで渡したパスにcdできない

ターミナル上で、コマンドで出力したパスに移動したいことがままあるのですが、パイプでcdコマンドに渡してもうまくいきません。

$ echo ~ | cd
# なにも起こらない

$ echo ~ | xargs cd
# なにも起こらない

$ cd "$(echo ~)"
# これはOK

ところで、実行可能ファイル形式のシェルスクリプトでcdしても、現在のシェルに反映されないという問題があります。

これは、ファイルからシェルスクリプトを実行した場合、サブシェルが起動しているためです。

これと同様の理由で、パイプでつないだ先の部分でcdしてもexec /bin/bashしても、元々のシェルには反映されません。

$ pwd | cd ~
# なにも起こらない

$ echo $$
32187
# パイプの前のコマンドはなんでもいい
$ pwd | cd ~;exec /bin/bash
$ echo $$ # プロセスIDが変化していない
32187

パイプを使い、さらに現在のシェルにcdを反映させるには、もはや新たにコマンドを実行するしかありません。

AppleScriptを使い無理やり実現

以下はiTerm2依存ですが、他のターミナルエミュレータでも同様のスクリプトは書けると思います。
(Build 3.1対応)

~/.bashrc
pcd () {
  if [ ! -p /dev/stdin ]; then
    if [ $# -ge 1 ]; then
      cd "$1"
      shift
      if [ $# -ge 1 ]; then
        echo "Too many arguments. After second arguments are not processed."
      fi
    else
      echo "ERROR: No stdin or argument"
      return 1
    fi
  else
    osascript -e "tell application \"iTerm\" to tell current session of current tab of current window to write text \"cd $(cat -)\""
  fi
}

(パイプからの)標準入力がなければ、引数を移動先ディレクトリとして普通にcdします。標準入力がある場合、そこにcdするコマンドをAppleScript経由で実行します。

どうせなら、渡された引数や標準入力がディレクトリパスか判断してdirnameしたり、後ろにパイプがないか判断してエラーチェックもしたいですね。

参考

13
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?