Strawberry Perlのインストールパスに使えないASCII記号が多すぎるのでまとめた

# まとめ

![ascii.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/0b997bdb-fd47-3485-8904-c0849c42f688.png)

~~この画像で全部済むので残りは読まなくて良いと思う。~~


# 環境

- Windows 10 Home 64-bit 22H2
- Strawberry Perl 5.32.1.1 64-bit https://strawberryperl.com/
- Google 日本語入力 2.28.4650.0


# 背景

Windows 向け Perl ディストリビューションである **Strawberry Perl** のインストーラーは、ユーザーが手動指定したインストールパスに**スペース**または**非 ASCII 文字**が含まれていると、続行を拒否してくる。

![error-with-space.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/f8455e26-9a8a-3695-13cd-265688cd8757.png)

> Strawberry Perl (64-bit) cannot be installed in a directory with spaces or non-ASCII characters.

> 拙訳<sup>（上付きは訳註）</sup>：
> Strawberry Perl (64-bit) は、スペースや非 ASCII 文字を<sup>（パスに）</sup>持つディレクトリにはインストールできません。

**気が利く。**
Perl はシェルスクリプトの延長線上みたいなもの（ほんとか？）である以上、インストールパスに変な文字が無いに越したことは無い。

直上のディレクトリ名に限らず、`C:\St\r aw\be\rry\` や `C:\St\ろ\be\rry\` みたいに途中のディレクトリ名が該当する場合でも全く同様に拒否される。

それは大変結構。
しかし、ではここでスペースの代わりに**カンマ**を入れてみると…

![error-with-comma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/eaecec59-128b-aa5f-c58a-cba1ea3126a9.png)

それでも全く同様に拒否される。
**カンマは ASCII 文字ですけど！？！？**

いや、まぁ、わからんでもない。
Bash とかのブレース展開機能は `{a,b,c}.txt` を `a.txt b.txt c.txt` に展開するし、なんかそういうのと競合したくないというのならわかる。
**でもエラー文はあくまで間違ってますけど！？！？！？**

で、色々試すと、どうやらパスに使えない ASCII 記号類は他にもいくつかある（むしろ使える方が少ない）ことがわかった。
ということで、Strawberry Perl のインストールパスには ASCII 文字のうちどれが使えてどれが使えないのか、調べ尽くしてみた。


# スペースでも非 ASCII 文字でもないくせに Strawberry Perl のインストールパスに使えない哀れな ASCII 記号どもはこちら！！

ついでにシェルや Perl での用途例も書き添えてみている。

| 文字符号 | 記号 | 用途例 |
|:-:|:-:|-|
| 0x23 | `#` | コメント、シバン、配列や引数のサイズ、変数の前方削除 |
| 0x24 | `$` | 様々な変数や書式、正規表現の行末、プロセス ID |
| 0x25 | `%` | 様々な指定子、変数の後方削除、Perl のハッシュ、cmd.exe の変数 |
| 0x26 | `&` | リダイレクト、コマンドの連結、論理積、`sed` の一致部 |
| 0x27 | `'` | 文字列のクォーテーション |
| 0x28 | `(` | 様々なグループ化、算術式評価、配列の宣言 |
| 0x29 | `)` | 様々なグループ化、算術式評価、配列の宣言 |
| 0x2C | `,` | ブレース展開の区切り、変数の小文字化 |
| 0x3B | `;` | コマンド行の区切り、`sed` の区切り、`for` や `case` の区切り |
| 0x3D | `=` | 代入、比較演算、変数のヌル合体代入 |
| 0x5E | `^` | パターン範囲の否定、変数の大文字化、正規表現の行頭、キャレット記法 |
| 0x60 | `` ` `` | コマンド置換、Perl の標準出力取得演算子 |
| 0x7B | `{` | 変数の展開や置換、様々なグループ化、正規表現の繰り返し |
| 0x7D | `}` | 変数の展開や置換、様々なグループ化、正規表現の繰り返し |
| 0x7E | `~` | ホームディレクトリ、正規表現比較 |

結構いっぱいあった。

ドル記号 `$`、波括弧 `{` `}` 辺りが使えないのは当然といったところ。
バッククォート `` ` ``、チルダ `~` も然り。

パーセント記号 `%` も、Perl や Windows にとっては大変警戒に値する記号だろう。

丸括弧 `(` `)` が使えないのはやや意外。
絶対に `C:\Program Files (x86)` 下にはインストールさせない、という意思の表れだろうか。
ただでさえスペースは使えないのに。


# 使える ASCII 記号類

逆に使える連中も列挙しておく。

| 文字符号 | 記号 | 用途例 |
|:-:|:-:|-|
| 0x21 | `!` | 論理否定、シバン、履歴展開、拡張 GLOB の否定 |
| 0x2B | `+` | 和、`set` のオプション解除、変数のヌル条件返り値 |
| 0x2D | `-` | 差、オプション、変数のヌル合体返り値、`cat` 等の「標準出力」指定 |
| 0x2E | `.` | 相対パス、ドットファイル、ブレース展開の範囲指定、正規表現の任意文字 |
| 0x40 | `@` | 配列や引数の全体の参照、拡張 GLOB の単一一致 |
| 0x5B | `[` | 条件評価、配列の中身の参照、パターン範囲 |
| 0x5D | `]` | 条件評価、配列の中身の参照、パターン範囲 |
| 0x5F | `_` | Perl のデフォルト変数（`$_`） |

少ないなぁ…。

ピリオド `.` が使えなかったらどう考えてもえらいことになるので、使えるのは順当。

ハイフンマイナス `-`、アンダースコア `_` も、もし禁じられていたらキャメルケース勢以外は泣き濡れて暮らしただろう。

感嘆符（エクスクラメーション）`!`、アットマーク `@`、角括弧 `[` `]` 辺りは割と危なそうな気もするが…。


# そもそも Windows で使えない ASCII 記号類

まず、当然だが `\`（バックスラッシュ、半角円記号）は Windows のパス区切りに使われるので、フォルダー名としては使えない。
`:`（コロン）もドライブ名に使うので使えない。

| 文字符号 | 記号 | 用途例 |
|:-:|:-:|-|
| 0x3A | `:` | 「何もしない」、一部の変数展開、履歴展開の修飾子、Windows のドライブ |
| 0x5C | `\` | エスケープ、Windows のパス区切り |

他にも、これらの文字は元から Windows のファイル名やフォルダー名に使うことができない。

| 文字符号 | 記号 | 用途例 |
|:-:|:-:|-|
| 0x22 | `"` | 文字列と変数のクォーテーション |
| 0x2A | `*` | 「とにかく全部」みたいなやつ全般 |
| 0x2F | `/` | 様々な置換、Windows 以外のパス区切り、cmd.exe のオプション |
| 0x3C | `<` | リダイレクト、大小比較、ビットシフト、ヒアドキュメント |
| 0x3E | `>` | リダイレクト、大小比較、ビットシフト |
| 0x3F | `?` | 終了ステータス、パターンの任意の 1 文字、算術式評価の三項演算子 |
| 0x7C | `\|` | パイプ、論理和、リダイレクト |

Strawberry Perl ではこいつらの対策もちゃんとされており、カンマとかとは別のエラーが出て拒否される。

![error-char-forbidden-by-os.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/6c951ebe-7706-35a9-1c81-5cc39d3932c2.png)

> The folder path '云々' contains an invalid character.

> 拙訳：
> フォルダーパス「云々」に不正な文字が含まれています。

ただ、`\` を全て `/`（スラッシュ）に置き換えたパス `C:/Strawberry/` で試したところ、また別のエラーとなった。

![error-slash-unavailable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/803ddf60-766e-db71-83f6-74337fe53592.png)

> The specified path '/Strawberry/' is unavailable.

> 拙訳：
> 指定されたパス「/Strawberry/」は利用不能です。

割と色々な種類のエラーがインストーラーに想定されていることがわかる。
エラー対応って大変だな～。


# ASCII 制御文字

記号ではないが、せっかくなので調べた。

ASCII 文字の 0x00～0x1F および 0x7F は**制御文字**となっている。

| 文字符号 | 略号 | 他の表現 | 名称 | 用途例 |
|:-:|:-:|:-:|:-:|-|
| 0x00 | NUL | `^@`&nbsp;`\0`&nbsp;␀ | ヌル文字 | `xargs` 等の安全な区切り文字 |
| 0x01 | SOH | `^A`&nbsp;␁ | ヘッディング開始 |  |
| 0x02 | STX | `^B`&nbsp;␂ | テキスト開始 |  |
| 0x03 | ETX | `^C`&nbsp;␃ | テキスト終結 | コマンド入力の中断時に Ctrl + C で入力 |
| 0x04 | EOT | `^D`&nbsp;␄ | 伝送終了 |  |
| 0x05 | ENQ | `^E`&nbsp;␅ | 問い合わせ |  |
| 0x06 | ACK | `^F`&nbsp;␆ | 肯定応答 |  |
| 0x07 | BEL | `^G`&nbsp;`\a`&nbsp;␇ | ベル |  |
| 0x08 | BS  | `^H`&nbsp;`\b`&nbsp;␈ | 後退 |  |
| 0x09 | HT  | `^I`&nbsp;`\t`&nbsp;␉ | 水平タブ | いわゆるタブ文字 |
| 0x0A | LF  | `^J`&nbsp;`\n`&nbsp;␊ | 行送り | UNIX と Mac の改行（LF）<br>Windows の改行（CR + LF） |
| 0x0B | VT  | `^K`&nbsp;`\v`&nbsp;␋ | 垂直タブ |  |
| 0x0C | FF  | `^L`&nbsp;`\f`&nbsp;␌ | 書式送り |  |
| 0x0D | CR  | `^M`&nbsp;`\r`&nbsp;␍ | 復帰 | 古い Mac の改行（CR）<br>Windows の改行（CR + LF） |
| 0x0E | SO  | `^N`&nbsp;␎ | シフトアウト |  |
| 0x0F | SI  | `^O`&nbsp;␏ | シフトイン |  |
| 0x10 | DLE | `^P`&nbsp;␐ | 伝送制御拡張 |  |
| 0x11 | DC1 | `^Q`&nbsp;␑ | 装置制御 1 |  |
| 0x12 | DC2 | `^R`&nbsp;␒ | 装置制御 2 |  |
| 0x13 | DC3 | `^S`&nbsp;␓ | 装置制御 3 |  |
| 0x14 | DC4 | `^T`&nbsp;␔ | 装置制御 4 |  |
| 0x15 | NAK | `^U`&nbsp;␕ | 否定応答 |  |
| 0x16 | SYN | `^V`&nbsp;␖ | 同期信号 |  |
| 0x17 | ETB | `^W`&nbsp;␗ | 伝送ブロック終結 |  |
| 0x18 | CAN | `^X`&nbsp;␘ | 取り消し |  |
| 0x19 | EM  | `^Y`&nbsp;␙ | 媒体終結 |  |
| 0x1A | SUB | `^Z`&nbsp;␚ | 置換 |  |
| 0x1B | ESC | `^[`&nbsp;␛ | 拡張 |  |
| 0x1C | FS  | `^\`&nbsp;␜ | ファイル分離 |  |
| 0x1D | GS  | `^]`&nbsp;␝ | グループ分離 |  |
| 0x1E | RS  | `^^`&nbsp;␞ | レコード分離 |  |
| 0x1F | US  | `^_`&nbsp;␟ | ユニット分離 |  |
| 0x7F | DEL | `^?`&nbsp;␡ | 削除 | ファイル名に使える（後述） |

そして基本的に、Windows で**制御文字をファイル名に使うことはできない**。
Strawberry Perl でももちろん使えない。

ただ、実際にそういう文字を外部からコピーしてインストーラーのパス欄に貼り付けてみると、その「使えなさ」にはちょっとだけ違いがあることに気付いた。
大抵の制御文字は **"an invalid character"** のエラーで普通に弾かれるのに対し、NUL（0x00：ヌル文字）、LF（0x0A：行送り）、VT（0x0B：垂直タブ）、FF（0x0C：書式送り）、CR（0x0D：復帰）の 5 種類だけは、貼り付けすらされずに何も入力されなかったことになった。
まぁ使えないのは同じだし、使おうともしない文字なのでどうでも良いけど。

あと、0x7F にあたる **DEL（削除文字）**<wbr>だけは、なぜか Windows で**ファイル名に使える**ようになっている。
エクスプローラーでのファイル改名時に Ctrl + Backspace を押すと、豆腐にはなるがちゃんと入力され、そのまま確定もできてしまう。

![del.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/872ab97e-79b9-d51d-efc6-9554d1e10435.png)

しかし当然、そんな異常事態を見逃す Strawberry Perl ではない。
パス欄に同じ方法で直接入力することはできないし、外部からコピペしてみても **"spaces or non-ASCII characters"** のエラーでしっかり弾いてくれる。
**削除文字は ASCII 文字ですけど！？！？！？！？！？！？**


# その他

せっかくのせっかくなので、Windows のファイル名における他の制約にも触れておく。

まず、ファイル名の末尾をピリオドやスペースにすることはできず、そのようなファイルを作ろうとすると末尾のそれが勝手に削除される。
Strawberry Perl もやはり同様で、`C:\Strawberry \` や `C:\Strawberry.\` みたいなパスを指定して一旦 "Next" を押してから "Back" してみると、パスが自動的に `C:\Strawberry\` に修正されている。

また、`AUX` 等の一部の予約名が使えない。
Strawberry Perl も、そのようなパスを指定するとまた別のエラーで拒否してくる。

![error-word-forbidden-by-os.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/d68ca01c-eb05-7803-beac-f7afa6b083d8.png)

> The folder path '云々' contains words that are not valid in folder paths.

> 拙訳：
> フォルダーパス「云々」に、フォルダーパスとして用いるには不正な語が含まれています。

**エラー対応って大変だな～。**


# まとめ

というわけで。

## まとめ画像（再掲）

![ascii.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/0b997bdb-fd47-3485-8904-c0849c42f688.png)

## Strawberry Perl のインストールパスに使えない文字

- 全ての非 ASCII 文字
- ASCII スペース文字
- 独自に禁止している ASCII 記号：`#` `$` `%` `&` `'` `(` `)` `,` `;` `=` `^` `` ` `` `{` `}` `~`
- Windows が禁止している ASCII 記号：`"` `*` `/` `:` `<` `>` `?` `\` `|`
  - `:` `\` はパス構造の記述にのみ使用可能
- 全ての ASCII 制御文字
- Windows が禁止している予約名や末尾規則に抵触する名前

## Strawberry Perl のインストールパスに使える文字

- ASCII アラビア数字
- ASCII ラテンアルファベット（大文字、小文字）
- 一部の ASCII 記号：`!` `+` `-` `.` `@` `[` `]` `_`
- パス構造の記述としての `:` `\`
- ただし、Windows が禁止している予約名や末尾規則に抵触しないこと

そんな感じ。


# 参考リンク

- Don’t install Perl in “Program Files” | Base Table
  https://basetable.wordpress.com/2012/11/19/dont-install-perl-in-program-files/
- シェルスクリプト（Bash）の記号の意味 - Qiita
  https://qiita.com/kou029w/items/3e1285e3cef14682f4fe
- Man page of BASH - JM Project (Japanese)
  https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html
- perlintro - Perl の概要 - perldoc.jp
  https://perldoc.jp/docs/perl/5.36.0/perlintro.pod
- 制御文字 - Wikipedia
  [https://ja.wikipedia.org/wiki/制御文字](https://ja.wikipedia.org/wiki/制御文字)
- Naming Files, Paths, and Namespaces - Win32 apps | Microsoft Learn
  &gt; Naming Conventions
  https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
  - 日本語版（現状では機械翻訳）：
    https://learn.microsoft.com/ja-jp/windows/win32/fileio/naming-a-file#naming-conventions
- WindowsとGitHubのファイル並び順の違いを、ASCII文字の範囲で具体的に確認した - Qiita
  https://qiita.com/Phroneris/items/2cb893a4eea88ae9e085 **←それは私です！**

&ZeroWidthSpace;

おわり