スペースの入ったパスの賢いお取り扱い
【Macターミナル】よく使うフォルダだから、とにかく楽して移動したい | 林檎コンピュータ
という記事を書いていて気づいたのだが、標準出力にパスを出して cd などをしたい時、パスにスペースが入っているとうまくいかない。
なんのことかという話だが、
path=~/'my folder'
cd $(echo $path)
だと、移動に失敗する、という話なのだ。
スペースを含むパス
ターミナルを使い始めたころ、よくつまずいたのは、パスに入ったスペースである。bash や zsh は、半角スペースを区切りと見なし、スペース以後の文字列をオプションやら引数として扱う。
しかし回避は簡単なのだ。
テスト用に、デスクトップに「space 入ってる」というフォルダを作成する。
mkdir ~/Desktop/'space 入ってる'
スペースは、バックスラッシュを前置することでエスケープできるはず。
name@MacBook-Air ~
$ cd ~/Desktop/space\ 入ってる
name@MacBook-Air ~/Desktop/space 入ってる
$
移動できた。
ほかにも、クオートやダブルクオートで囲めば移動できるはず。
ホームを表わすチルダは、クオートで囲むと展開できないので、以下のように書いた。
cd ~/Desktop/'space 入ってる'
# -> 移動できる
cd "$HOME/Desktop/space 入ってる"
# -> 移動できる
標準出力?を引数に使うと失敗する
ここまではいい。
筆者がやりたいのは、以下のようなことだ。
path="$HOME/Desktop/space 入ってる"
cd $(echo $path)
実行すると以下のようになる。
name@MacBook-Air ~
$ path="$HOME/Desktop/space 入ってる"
name@MacBook-Air ~
$ cd $(echo "$path")
cd: string not in pwd: /Users/username/Desktop/space
スペースの箇所で切れてしまい、移動できない。
しかしバックスラッシュを使えばいけるはず。
変数に:q
をくっつければエスケープされた文字列を出力してくれる。
$ echo $path:q
/Users/username/Desktop/space\ 入ってる
これをふまえて、以下のように書いた。
$ cd $(echo $path:q)
cd: string not in pwd: /Users/username/Desktop/space\
駄目みたい。
ダブルクオートを試してみる。
$ cd $(echo \"$path\")
cd: string not in pwd: "/Users/username/Desktop/space
なぜか駄目。
変数 path を書き直してシングルクオートでもやってみる。
$ path='/Users/username/Desktop/space 入ってる'
$ cd $(echo \'$path\')
cd: string not in pwd: '/Users/username/Desktop/space
どうしても駄目。
バックスラッシュもクオートも関係ねぇ、スペースをまず評価するんだ、とでもいうような固陋な態度である。でなければ、筆者がなにか勘違いしているのだろう。
eval コマンド
この問題は eval コマンドで解決する。
$ path="$HOME/Desktop/space 入ってる"
$ eval cd $(echo $path:q)
# -> 移動できる
$ eval cd $(echo \'$path\')
# -> 移動できる
$ eval cd $(echo \"$path\")
# -> 移動できる
eval コマンドというのは、
「eval 文字列」で文字列をコマンドとして実行します。「eval 文字列1 文字列2 ……」のように文字列を複数指定した場合、スペースをはさんで連結後、シェルに実行させます。
【 eval 】コマンド――文字列を評価、連結して実行する:Linux基本コマンドTips(170) – @IT
とのこと。
echo が出力する文字列だと、単なる平文みたいに扱われてクオートもバックスラッシュも意味を成さないのかもしれない。「スペースをはさんで連結後」というところがポイントっぽい。
ということは、
pic='cd ~/Pictures'
eval $pic
とやれば、ピクチャフォルダへ移動できるはずだ。実際に試すと移動できる。
なんか凄い。知っていればいろいろ役に立ってくれそうなコマンドだと思う。
最近のコメント