「Windowsでエクスプローラーからフォルダを各種ターミナルで開く」の版間の差分

Notion-MW
Notion-MW
 
(同じ利用者による、間の4版が非表示)
51行目: 51行目:
* powershell.exe
* powershell.exe
** -Commandがなくても付けたのと同じ扱いになる?
** -Commandがなくても付けたのと同じ扱いになる?
*** 逆に、-Commandを付けなければいけないという点を除いてはpwshがpowershellの上位互換という感覚である。
*** 逆に、-Commandを付けなければいけないという点を除いてはpwshがpowershellの上位互換という感覚である(新しいのでそれはそう)。
** <code>`</code>や<code>&#91;&#93;</code>を含むフォルダの扱いにバグがあり、cmdなどでこれらのフォルダをカレントディレクトリとした状態で5系のPowerShellを起動すると<code>C&#58;\</code>や<code>C&#58;\Windows\System32\WindowsPowerShell\v1.0&gt;</code>をカレントディレクトリとして起動される(たとえば<code>C&#58;\somefolder&#93;&#91;</code>なら前者、<code>C&#58;\somefolder&#91;&#93;</code>なら後者)。
** <code>`</code>や<code>&#91;&#93;</code>を含むフォルダの扱いにバグがあり、cmdなどでこれらのフォルダをカレントディレクトリとした状態で5系のPowerShellを起動すると<code>C&#58;\</code>や<code>C&#58;\Windows\System32\WindowsPowerShell\v1.0&gt;</code>をカレントディレクトリとして起動される(たとえば<code>C&#58;\somefolder&#93;&#91;</code>なら前者、<code>C&#58;\somefolder&#91;&#93;</code>なら後者)。
** &#45;Fileを使用してスクリプトを実行するとき、ダブルクォーテーションで囲われていない <code>&#45;</code> が引数に含まれているとエラーになるバグがある。
** &#45;Fileを使用してスクリプトを実行するとき、ダブルクォーテーションで囲われていない <code>&#45;</code> が引数に含まれているとエラーになるバグがある。
75行目: 75行目:
これを防ぐ方法はいくつかある。ちなみに、<code>%%</code>でのエスケープというのはバッチファイルの中だけの話で、今回の場面では以下より簡単なエスケープ方法は多分ないと思う。
これを防ぐ方法はいくつかある。ちなみに、<code>%%</code>でのエスケープというのはバッチファイルの中だけの話で、今回の場面では以下より簡単なエスケープ方法は多分ないと思う。


<ul>
<ol style="list-style-type: decimal;">
<li><p>既に定義されているかもしれない環境変数をバックアップし、一時的にその中身を<code>%</code>に変えて使用することでリテラル文字としての<code>%</code>を表現し、後で元に戻す。</p>
<li><p>既に定義されているかもしれない環境変数をバックアップし、一時的にその中身を<code>%</code>に変えて使用することでリテラル文字としての<code>%</code>を表現し、後で元に戻す。</p>
<p>すなわち、<code>MY_PERCENT</code>のような変数の中身をバックアップし、<code>MY_PERCENT</code>の中身を<code>%</code>に変え、未知の文字列中の<code>%</code>をすべて<code>%MY_PERCENT%</code>にすることで<strong>この部分が置換によって</strong><strong><code>%</code></strong><strong>に変わるのを利用して</strong><code>%</code>をそのまま渡すということである(環境変数の置換は左から順に行われるため、たとえば<code>%MY_PERCENT%PATH%MY_PERCENT%</code>の<code>%PATH%</code>が置換されることはない)。受け渡しが終わったら<code>MY_PERCENT</code>の中身を復元する。</p>
<p>すなわち、<code>MY_PERCENT</code>のような変数の中身をバックアップし、<code>MY_PERCENT</code>の中身を<code>%</code>に変え、未知の文字列中の<code>%</code>をすべて<code>%MY_PERCENT%</code>にすることで<strong>この部分が置換によって</strong><strong><code>%</code></strong><strong>に変わるのを利用して</strong><code>%</code>をそのまま渡すということである(環境変数の置換は左から順に行われるため、たとえば<code>%MY_PERCENT%PATH%MY_PERCENT%</code>の<code>%PATH%</code>が置換されることはない)。受け渡しが終わったら<code>MY_PERCENT</code>の中身を復元する。</p>
89行目: 89行目:
<li>[https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables Environment Variables &#45; Win32 apps | Microsoft Learn]では「<code>&#61;</code>は環境変数に使えない」と書かれていて、ダイアログからでも設定はできないが、レジストリだと無理やり設定できる。
<li>[https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables Environment Variables &#45; Win32 apps | Microsoft Learn]では「<code>&#61;</code>は環境変数に使えない」と書かれていて、ダイアログからでも設定はできないが、レジストリだと無理やり設定できる。
<ul>
<ul>
<li>ユーザー環境変数に設定する分にはとりあえず問題なさそうだが、システム環境変数にレジストリから<code>&#61;</code>(と、<code>&#61;</code>を名前に含むいくつかの変数。どれが原因かは正確にはわからない)を無理やり追加したら<strong>0xc000021のブルースクリーンでWindowsが起動しなくなった</strong>(該当の変数を全て削除したら治った)のでこれはやってはいけない。</li></ul>
<li>ユーザー環境変数に設定する分にはとりあえず問題なさそうだが、システム環境変数にレジストリから<code>&#61;</code>(と、<code>&#61;</code>を名前に含むいくつかの変数。どれが原因かは正確にはわからない)を無理やり追加したら<strong>0xc000021のブルースクリーンでWindowsが起動しなくなった</strong>(Linuxからchntpwで該当の変数を全て削除したら治った)のでこれはやってはいけない。</li></ul>
</li>
</li>
<li>ちなみに、<code>&#61;</code>や<code>%</code>はUnix側では特殊文字ではないので、printfとの適用順はあまり気にする必要はない。</li></ul>
<li>ちなみに、<code>&#61;</code>や<code>%</code>はUnix側では特殊文字ではないので、printfとの適用順はあまり気にする必要はない。</li></ul>
98行目: 98行目:
</li>
</li>
<li>ただ、<code>&#61;&#61;%</code>を<code>%</code>に置換するという操作はPowerShellやshにとっては容易でもcmdにとっては不可能に近いので、最終的な呼び出し先がcmdであるときには採用しづらい。</li></ul>
<li>ただ、<code>&#61;&#61;%</code>を<code>%</code>に置換するという操作はPowerShellやshにとっては容易でもcmdにとっては不可能に近いので、最終的な呼び出し先がcmdであるときには採用しづらい。</li></ul>
</li></ul>
</li></ol>


また、今回の記事ではcmdやvbsのRunを経由してコマンドを実行しているものが多くあるが、<strong>このスクリプトの内容自体もエスケープが必要</strong>である。つまり、例えば<code>cmd /c</code>の内側に<code>$mypath.Replace(&#39;%&#39;,&#39;%MY_PERCENT%&#39;)</code>というPowershellコードが含まれるなら、<code>&#39;,&#39;</code>や<code>MY_PERCENT</code>という環境変数が定義されていた時にその部分が置換されてしまう。これを回避するのはそこまで難しくなく、この例であれば<code>$mypath.Replace(&#39;%&#39;.Trim(&#39;&#61;&#39;),&#39;%&#39;.Trim(&#39;&#61;&#39;)+&#39;MY_PERCENT%&#39;)</code>のように<code>&#61;</code>を含む無意味なコードを挿入すればよい。また、<code>%</code>をいったん<code>&#61;&#61;%</code>にしている部分に関しては、<code>&#61;&#61;%</code>ではなく<code>&#61;&#61;%&#61;&#61;</code>にすることで問題を避けられるだろう。無駄に複雑になるのでスクリプト例ではそのような措置はしていない。
また、今回の記事ではcmdやvbsのRunを経由してコマンドを実行しているものが多くあるが、<strong>このスクリプトの内容自体もエスケープが必要</strong>である。つまり、例えば<code>cmd /c</code>の内側に<code>$mypath.Replace(&#39;%&#39;,&#39;%MY_PERCENT%&#39;)</code>というPowershellコードが含まれるなら、<code>&#39;,&#39;</code>や<code>MY_PERCENT</code>という環境変数が定義されていた時にその部分が置換されてしまう。これを回避するのはそこまで難しくなく、この例であれば<code>$mypath.Replace(&#39;%&#39;.Trim(&#39;&#61;&#39;),&#39;%&#39;.Trim(&#39;&#61;&#39;)+&#39;MY_PERCENT%&#39;)</code>のように<code>&#61;</code>を含む無意味なコードを挿入すればよい。また、<code>%</code>をいったん<code>&#61;&#61;%</code>にしている部分に関しては、<code>&#61;&#61;%</code>ではなく<code>&#61;&#61;%&#61;&#61;</code>にすることで問題を避けられるだろう。無駄に複雑になるのでスクリプト例ではそのような措置はしていない。
199行目: 199行目:
<p>カレントディレクトリをコンソールに出力する。(ちなみにpwdの由来はprint working directoryなのでそれに倣った)</p></li></ul>
<p>カレントディレクトリをコンソールに出力する。(ちなみにpwdの由来はprint working directoryなのでそれに倣った)</p></li></ul>


<span id="注意&#58;-当初は後述のnoworkingdirectoryを知らなかったので1の方法に頼っていたが実際には2の方法のほうが簡明なのでそちらを使うことを勧める1は残しておくが読む必要はあまりない"></span>
<span id="注意&#58;-当初は後述のnoworkingdirectoryを知らなかったので1の方法に頼っていたが実際には2の方法のほうが簡明なのでそちらを使うことを勧める1と11は残しておくが読む必要はあまりない"></span>
== 注意&#58; 当初は後述のNoWorkingDirectoryを知らなかったので1.の方法に頼っていたが、実際には2.の方法のほうが簡明なので、そちらを使うことを勧める。1.は残しておくが、読む必要はあまりない。 ==
== 注意&#58; 当初は後述のNoWorkingDirectoryを知らなかったので1.の方法に頼っていたが、実際には2.の方法のほうが簡明なので、そちらを使うことを勧める。1.(と1.1.)は残しておくが、読む必要はあまりない。 ==


   
{{UnderConstruction|Windowsでエクスプローラーからフォルダを各種ターミナルで開く}}


<span id="1標準入力から受け取る場合"></span>
<span id="1標準入力から受け取る場合"></span>
409行目: 409行目:
<p><code>sh &#45;c &quot;IFS&#61;&#59;echo $&#42;&quot; &#45;&#45; &quot;%V</code></p>
<p><code>sh &#45;c &quot;IFS&#61;&#59;echo $&#42;&quot; &#45;&#45; &quot;%V</code></p>
<ul>
<ul>
<li>最後が<code>&quot;%V</code>と閉じられていないのはミスではなく、<code>&quot;%V&quot;</code>としてしまうと<code>C&#58;\</code>のときに<code>C&#58;&quot;</code>が渡されてしまうのでそれを避けるためである(これはかなりトリッキーなのでもう少し真面目にやってもいいとは思う)。</li>
<li>最後が<code>&quot;%V</code>と閉じられていないのはミスではなく、<code>&quot;%V&quot;</code>としてしまうと<code>C&#58;\</code>のときに<code>C&#58;&quot;</code>が渡されてしまうのでそれを避けるためである(これはかなりトリッキーなのでもう少し真面目にやってもいいかなとは思う)。</li>
<li>UNCパスの最初の<code>\\</code>が<code>\</code>に変わってしまう(手元では、Cygwinの場合は<code>\\?\</code>のみで発生している?)という問題があり、適宜置換する必要がある。</li></ul>
<li>UNCパスの最初の<code>\\</code>が<code>\</code>に変わってしまう(手元では、Cygwinの場合は<code>\\?\</code>のみで発生している?)という問題があり、適宜置換する必要がある。</li></ul>
</li></ul>
</li></ul>
468行目: 468行目:
<p><code>&quot;C&#58;\Program Files\Git\git&#45;bash.exe&quot; &#45;c &quot;IFS&#61;&#59;cd $(echo $&#42;|/bin/sed &#39;s/\\\\/\\\\\\\\/&#39;|/bin/cygpath &#45;f &#45;)&#59;exec bash&quot; &#45;&#45; &quot;%V</code></p>
<p><code>&quot;C&#58;\Program Files\Git\git&#45;bash.exe&quot; &#45;c &quot;IFS&#61;&#59;cd $(echo $&#42;|/bin/sed &#39;s/\\\\/\\\\\\\\/&#39;|/bin/cygpath &#45;f &#45;)&#59;exec bash&quot; &#45;&#45; &quot;%V</code></p>
<ul>
<ul>
<li><p>Git Bashのインストーラにより設定される「Git Bash Here」メニューでは以下のようになっている。</p>
<li><p>ちなみに、Git Bashのインストーラにより設定される「Git Bash Here」メニューでは以下のようになっている。</p>
<p><code>&quot;C&#58;\Program Files\Git\git&#45;bash.exe&quot; &quot;&#45;&#45;cd&#61;%v.&quot;</code></p>
<p><code>&quot;C&#58;\Program Files\Git\git&#45;bash.exe&quot; &quot;&#45;&#45;cd&#61;%v.&quot;</code></p>
<p>これは、特殊文字にはすべて対応しているが、(NoWorkingDirectoryをつけたとしても)<code>\\?\</code>で始まるパスではうまくいかない。最後の「.」はよくわからないがこれを付けておくと<code>&#45;&#45;cd</code>がうまくやってくれるっぽい。</p></li></ul>
<p>これは、特殊文字にはすべて対応しているが、(NoWorkingDirectoryをつけたとしても)<code>\\?\</code>で始まるパスではうまくいかない。最後の「.」はよくわからないがこれを付けておくと<code>&#45;&#45;cd</code>がうまくやってくれるっぽい。</p></li></ul>