ディレクトリ名に記号を使いたいので調べてみた

## ディレクトリ名に記号を使うメリット

制作上のガイドラインの中に、大抵の場合、画像は「img」、JavaScriptは「js」、CSSは「css」と名称とするような取り決めがありますが、FTP などファイル一覧で表示した際に、通常のコンテンツ用ディレクトリと予約名ディレクトリが混在するので、探すのがメンドいという問題（？）があります。

例）予約名ディレクトリがコンテンツのディレクトリと混在するケース

    admin
    company
    contact
    css <<
    ir
    img <<
    js <<
    service

そこで、予約ディレクトリ名の頭に記号を付与することで、表示順を集約してコンテンツのディレクトリ名と明示的な切り分けを行えないかと考えました。

例）予約名ディレクトリをコンテンツディレクトリと明確に切り分けたケース

    _css <<
    _images <<
    _js <<
    admin
    company
    contact
    ir
    service

視覚的に差別化が図れるのと、ソートを掛けると予約ディレクトリが先頭にやってくるので、エクスプローラーや Finder で表示した時にアクセス頻度の高いリソースディレクトリに最短でアクセスできて便利、といったメリットもあります。

ハイフンやアンダースコアはいつも良く使っている記号なので、これらを使えば問題なさげですが、往々にしてこれらの記号には別の意図を持たせていることが多いので、実際に使える記号は他にないのか調べてみました。

## URI 上の文字制約

URI の定義は [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt) で定義されています。  
URI の構成を見ると以下のような定義がされています。

    3.  Syntax Components

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
    scheme     authority       path        query   fragment

今回の対象となるのはディレクトリ名なので、path 構成要素において許容されている文字であればOK、ということになります。

さらに 個別の箇所を見てみると、以下のような定義がされています。

    RFC 3986                   URI Generic Syntax               January 2005

      dec-octet     = DIGIT                 ; 0-9
                    / %x31-39 DIGIT         ; 10-99
                    / "1" 2DIGIT            ; 100-199
                    / "2" %x30-34 DIGIT     ; 200-249
                    / "25" %x30-35          ; 250-255

      reg-name      = *( unreserved / pct-encoded / sub-delims )

      path          = path-abempty    ; begins with "/" or is empty
                    / path-absolute   ; begins with "/" but not "//"
                    / path-noscheme   ; begins with a non-colon segment
                    / path-rootless   ; begins with a segment
                    / path-empty      ; zero characters

      path-abempty  = *( "/" segment )
      path-absolute = "/" [ segment-nz *( "/" segment ) ]
      path-noscheme = segment-nz-nc *( "/" segment )
      path-rootless = segment-nz *( "/" segment )
      path-empty    = 0<pchar>

      segment       = *pchar
      segment-nz    = 1*pchar
      segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
                    ; non-zero-length segment without any colon ":"

      pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"

      query         = *( pchar / "/" / "?" )

      fragment      = *( pchar / "/" / "?" )

      pct-encoded   = "%" HEXDIG HEXDIG

      unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
      reserved      = gen-delims / sub-delims
      gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
      sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                   / "*" / "+" / "," / ";" / "="

この定義を見てみると path のパターンは segment で 構成されていて、segment は pchar で構成されていることが分かります。

つまり、 path で使える文字列は実質

>pchar = unreserved / pct-encoded / sub-delims / ":" / "@"

ということになります。
ここから使える記号文字のみを抽出すると、

`. _ - ~ % ! $ & ' ( ) * + , ; = : @`

上記が定義上、利用が許可されている文字となります。

## 記号文字の絞り込み

様々な条件で使用できない記号文字を消去法で除外していきます。生き残った記号がディレクトリ名に使用できる候補になります。

### 1. エンコード記号 「%」

前述の pchar には pct-encoded がありましたが、「%」 はURIエスケープをする際に使われる記号です。  

ディレクトリ名にこの記号使うと、アクセス時には `http://example.com/%25css/style.css` のような形で置き換える必要があり、取り回しに不便ですので除外しておきます。

残候補　  `. _ - ~ ! $ & ' ( ) * + , ; = : @`

### 2. ファイルシステム上の制約 「:」「*」「;」

OS のファイルシステムが取り扱えない文字列はそもそも物理的にディレクトリを作成できないので除外します。

|OS|制約文字|
|:------|:------|
|Windows|/ > < ? : " \ * &#124; ;|
|Linux|/ \0|
|Mac|Linuxに準ずる|

残候補　`. _ - ~ ! $ & ' ( ) + , = @`

※この時点で、上記で構成されたフォルダ名にアクセスすると一通りのブラウザ環境でアクセスできることを確認できました。

### 3. 既に暗黙の了解として意味がある文字 「.」「_」

一般的に 「.」 から始まるディレクトリは不可視のシステムファイルや設定ファイルとして扱われます。  
また、「_」 から始まるディレクトリも、アプリケーションが出力したり、一時的な退避をしたり、と何らかの意図をもって運用されているケースが多いです。
既に意味のある文字列を使うと混乱の元なので、ここでは除外対象とします。

残候補　`- ~ ! $ & ' ( ) + , = @`

### 4. HTML記述上の制約 「'」「&」

ディレクトリ名にシングルクオート 「'」 が使われていると、パス情報を記載する際に属性値がシングルクオートで括られていた場合、URI エスケープ記述をする必要が出てきます。
例） `href='../%27css/style.css'`  

また、アンバサンド 「&」 もHTML上では実体参照で記述する必要が推奨されています。
例） `href="../&amp;css/style.css"`

置き換えの手間を考えると除外対象とした方が良さそうです。

残候補　`- ~ ! $ ( ) + , = @`

### 4. プログラム言語の予約文字 「$」

いくつかのプログラム言語では変数を示す記号が 「$」 で表現されることがあります。  
ヒアドキュメント内に記述された 「$」 から始まる文字列は変数展開されてしまうため、これを回避するためにはプログラムコード上でエスケープ処理をする必要があります。

```php
<?php
echo <<<EOD
  <img border="0" src='$img/btn.gif' />
EOD;
// $img が定義されていなければ <img border="0" src='/btn.gif' /> と出力される
?>

```
これらの状況を想定すると除外対象とした方が良さそうです。

残候補　`- ~ ! ( ) + , = @`

### 5. Firefox の文字取り扱い 「(」「)」

 「(」「)」は Firefox のみ、ロケーションバーから URI をコピペするとなぜかエスケープしされた状態でコピーされます。
エスケープしなくても普通にアクセスできるのですが、ブラウザとエディタ間で URI のやり取りをすると表記上の揺らぎが発生する可能性があるのが若干気持ち悪いです。
また、単純にディレクトリ名の先頭に置くには文字的にそぐわない気もするので除外対象としておきます。

残候補　`- ~ ! + , = @`


## まとめ

ということで生き残った文字列は `- ~ ! + , = @` になりました。

後は好みの問題のような気もしますが、ディレクトリ名の先頭に来て座りの悪い文字「,」iやlとのような文字と交じると視認性が悪くなる「!」は避けるとすると、`- ~ + = @` の中から選ぶのが良さそうです。

個人的には先頭に来ても座りが良く、視認性の高い「@」推しです。

***

…と、ここまで書いておいてなんですが、ディレクトリ名に記号を使っているケースにあまり遭遇したことがありません。自分の把握していない範囲で、不都合な要因があったりするのでしょうか…

こういった理由で記号は使うべきではない、とかご指摘、ツッコミ大歓迎です。

## 【2020/01/27 追記】

はてブのコメントで指摘があったことに先ほど気が付きました。
https://b.hatena.ne.jp/entry/4641835331357261569/comment/kibitaki
> RFCまで引きながらreserved読めないアクロバティック解釈してる。

確かに 自分はディレクトリにまつわる URI コンポーネントとその仕様のところしかつまんでいなかったので、改めて reserved の箇所について読み直してみました。

https://www.ietf.org/rfc/rfc3986.txt

> 2.2.  Reserved Characters
> URIs include components and subcomponents that are delimited by
> characters in the "reserved" set.  These characters are called
> "reserved" because they may (or may not) be defined as delimiters by
> the generic syntax, by each scheme-specific syntax, or by the
> implementation-specific syntax of a URI's dereferencing algorithm.
> If data for a URI component would conflict with a reserved
> character's purpose as a delimiter, then the conflicting data must be
> percent-encoded before the URI is formed.

reserved で定義される文字は URI コンポーネントの区切り文字として機能するため、予約文字と呼び、URI コンポーネントのデータが**区切り文字としての予約文字の目的と競合する場合**は、URI が形成される前に競合するデータをパーセントエンコードする必要がある。

とありました。今回はコンポーネントの区切り文字として予約文字が使われない箇所の使用で競合はしないので、パーセントエンコードをしなくても大丈夫と解釈しても良さそう。（けど、ちょっと自信ない）

何にせよ万全を期すのであれば、 reserved に含まれる文字列を避けて、 unreserved の文字列記号、`- . _ ~` を使うのが確実かもしれません。

4年も前の記事で今さら感ありますが、未だに見て頂けているようですので、一応補足の追記をさせて頂きました。