Windows でファイル名に使えない文字

こんなキャッチーな見出しだとイヤな予感もする…。

そもそも Windows を主食にしてる人にとったら「んなの常識だろ」な人たちの方が多数派と思うから、そういう人ならこんなネタに飛び付くはずはない、と信じたい。逆に「初めて知ったわ、ありがとう」というヒト向けではないと思う、このネタ。

wget でね、あるサイトの動的生成ページを定期的に取りに行くスクリプトを書こうとしてさ、30分以上悩んでしまった、というしょーもない話。MSYS のせいだ。

「動的生成ページ」なので、クエリパラメータをくっつけて wget でお取り寄せしたいわけなのね。取り寄せたページが更新日付情報を持ってないこともあって、取り寄せたページをお取り寄せ日付時刻付きのファイル名にしたい、っと:

間違い探し
1 #! /bin/sh
2 dt=`date +'%Y%m%d%H%M%S'`
3 wget --no-check-certificate \
4     --output-document="${dt}_"'tophoge.php?type=UMA' \
5     'https://yourhoge.com/tophoge.php?type=UMA'

としちゃったわけだわ。

わかるヒトはすぐにわかる。けどワタシは MSYS のアホさのせいで、何が悪いのかすぐにわからず弱った。

これはヒドいよなぁ:

1 [me@host: ~]$ touch '?'
2 touch: cannot touch `?': No such file or directory

一応 Python で、使える文字検証プログラムを(やってみるまでもないけど)書いてみる:

 1 # -*- coding: utf-8 -*-
 2 import io
 3 import os
 4 
 5 def _try_create(c):
 6     fn = ".tmp" + c
 7     try:
 8         with io.open(fn, "w") as fo:
 9             pass
10         os.remove(fn)
11     except Exception as e:
12         print(c, e)
13 
14 if __name__ == '__main__':
15     for i in range(33, 127):
16         c = chr(i)
17         #if c not in ("/", "\\", ":"):
18         _try_create(c)

結果:

1 ('"', IOError(22, 'Invalid argument'))
2 ('*', IOError(22, 'Invalid argument'))
3 ('/', IOError(22, 'Invalid argument'))
4 (':', IOError(22, 'Invalid argument'))
5 ('<', IOError(22, 'Invalid argument'))
6 ('>', IOError(22, 'Invalid argument'))
7 ('?', IOError(22, 'Invalid argument'))
8 ('\\', IOError(22, 'Invalid argument'))
9 ('|', IOError(22, 'Invalid argument'))

ワタシはちょっと勘違いしていたんだけれど、この結果は explorer からファイル名を決める際に叱られるのとおんなじ文字セットなのよね。なんか昔「explorer からは作れないけどコマンドプロンプトからは作れるファイル名」があったはず、と思ったが、これは「拡張子しかないファイル名」と混同してた。

この「ファイル名に使えない文字」は Windows のは不条理なのが多くて昔から嫌いでさ。今はちょっとわからんけど Unix はディレクトリ区切りの「/」以外の ascii 32~126 は全部使えるのね。けど Windows のこれは、理由が不明なのばっかでさ。そして「?」はどういうわけだかこれまで気付かなかった。これは UNC 表記と衝突するからか…。

ちなみにこういう「常識だろ!」に案外気付かないのは、例えば今の例の場合の wget なら今回みたいに自分で出力ファイルを決めることをしない限りは勝手にうまくやってくれるし、例えば Python スクリプトからファイル名を決める場合なんかは例えば urlsafe_b64encode みたいなものに頼るからね、ふつー。なので案外気付かないまま生活出来る。ま、そんなもんだ。