やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

WindowsとLinuxのパス区切記号が違うせいでインライン・コマンドにできなかった

前回のつづき。

前回まで

ファイルを一発作成したい。秀丸ファイラで一発ファイル作成(PowerShellインライン版)でできたが、実行速度が遅すぎた。

そこで前回Linuxコマンドで実装しようとした。しかし、出力先ディレクトリを指定することができなかった。

今回

出力先ディレクトリを指定することができなかった経緯。

対象環境

やりたかったこと

MinGW/msysでは以下のコマンドで実行できる。

dir='C:\\あ い\\'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch "$dir$fname";

cmd.exeでは以下のコマンドで実行できる。

bash -c "dir='C:\\あ い\\'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"

上記コマンドのディレクトリ部分C:\\あ い\\秀丸ファイラのカレントディレクト%Vにしたい。

C:\MinGW\msys\1.0\bin\bash.exe  -c "dir='%V'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"

しかし、これは動作しない。WindowsLinuxのパス区切記号が違うことが原因である。

問題

パス区切記号

問題はパスの区切文字である。

秀丸ファイラの%Vディレクトリ文字列を渡せる。しかし、そのパス区切記号が\なのが問題になる。\Linuxシェル上ではエスケープ文字である。たとえばC:\a\b\だと、C:abになってしまう。Linuxシェル上でのパス区切記号は\である。シェルに渡す前に\/に置換する必要がある。または、\\のようにする必要がある。

インラインにできない

Windowsのコマンドで\/に置換する方法はある。set dir=%Vで変数にディレクトリ名を入れ、set dir=%dir:\=/%とすることで置換できる。しかし、バッチファイルにしないと使えない。パイプ連結したコマンドでは使えない。結果、秀丸ファイラでインライン・コマンドとして登録することができない。

replace.bat

set dir=C:\a\b\
echo %dir:\=/%

set dir=C:\a\b\
set dir=%dir:\=/%
echo %dir%

pause

置換するには一度変数に代入せねばならない。しかし、インラインにすると代入ができなくなった。その経緯は以下。

&で繋げても変数の状態が継承されない

"Batch 1行に複数文"で検索するとこちらがヒット。感謝。Batchでは1行に複数文を書くとき、&を使うらしい。Shellでは;だった。

> echo a & echo b
a
b

これを使ってパス区切記号\/に置換してからbashに渡すつもりのコマンドを以下に書いた。

set dir=%V & set dir=%dir:\=/% & bash -c "dir=%dir%; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"

しかしset dir=...での代入が反映されなかった。順に検証する。

まずはcmd.exeにて以下のコマンドを叩いてみた。ディレクトリ名にC:\dirを仮に設定しておく。

set dir=C:\dir & set dir=%dir:\=/% & bash -c "dir=%dir%; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"

しかし、Windowsset dir=C:\dirが反映されていない。

set dir=C:\dir & echo %dir%

以下のようにすると代入される。

set dir=C:\dir
echo %dir%

しかし上記は改行コードが含まれるためバッチファイルに書くしかない。インラインにできない。

どうやら&で繋ぐと変数の状態は継承されないらしい。Linux(sh,bash)の;で繋ぐ方法なら変数の状態を継承できたのに…。でも、Linux(sh,bash)に\のパス区切記号を使った文字列を渡してもエスケープされてしまうから肩代わりできない…。

かくしてインラインを断念し、スクリプトファイルにすることと相成った。

ほかの方法

Windows

諸悪の根源はパス区切記号である。やはりWindows、お前か。

dateコマンド

べつにWindowsコマンドだけで解決できれば、Linuxコマンドなど使わずにすんだ。パス区切記号が何であれ、問題にはならなかった。しかし、WindowsのdateコマンドはLinuxのdateコマンドのようにフォーマットできない仕様…。

%time%, %date%

じつはWindowsには%time%, %date%という日時を取得できる特殊な変数がある。しかし、バージョンによって取得できる書式が異なっているなど汎用性にかける。また、一部ゼロ埋めされていないなどの問題もある。その加工には置換が必要。先述のとおり、置換するにはバッチファイル化が必要でありインラインにできない。

学習が無駄になりそう

動作するなら何でもいいが、せっかくなら学習や成果物を流用できる可能性が高いほうがいい。そう考えるとWindowsよりLinuxになる。元々使えない上に、すでにオワコンOSのコマンドにそこまで執心するより、未来のあるLinuxコマンドで実装したほうが幸せになれると思った。

PowerShellは重い

WindowsにはPowerShellがある。これで解決したのが秀丸ファイラで一発ファイル作成(PowerShellインライン版)である。実行速度が遅いので別解を求めている最中。

Python

ところで、未だにbatch, shellで悩み続けている。糞スクリプトであるBatchから脱却したくてPythonを使ってみたのに今回は使えていない。Pythonではコマンド環境でインラインはできない、と思うから。

ググるこちらがヒット。感謝。しかし、結局Pythonファイルを作成するのでインラインにはできなそう。ぐぬぬ

所感

というわけでインラインは諦めて、次回スクリプトファイルを作る。