このコード:
for root, dirs, files in os.walk('.'):
print(root)
私にこのエラーを与えます:
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 27: surrogates not allowed
このような有毒な文字列を取得せずにファイルツリーをどのようにたどりますか?
Linuxでは、ファイル名は「単なるバイト」であり、必ずしも特定のエンコーディングでエンコードされているわけではありません。 Python 3はすべてをUnicode文字列に変換しようとします。そうすることで、開発者はバイト文字列をUnicode文字列に変換し、元のエンコーディングを知らずに損失することなく元に戻すスキームを考え出しました。 「不良」バイトをエンコードする部分的なサロゲートですが、通常のUTF8エンコーダーは端末への印刷時にそれらを処理できません。
たとえば、次は非UTF8バイト文字列です。
>>> b'C\xc3N'.decode('utf8','surrogateescape')
'C\udcc3N'
ユニコードとの間で損失なく変換できます:
>>> b'C\xc3N'.decode('utf8','surrogateescape').encode('utf8','surrogateescape')
b'C\xc3N'
ただし、印刷することはできません。
>>> print(b'C\xc3N'.decode('utf8','surrogateescape'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 1: surrogates not allowed
デフォルト以外のエンコーディングのファイル名をどうするかを理解する必要があります。おそらく、元のバイトにエンコードして、未知の置換でデコードするだけです。これを表示に使用しますが、ファイルにアクセスするために元の名前を保持します。
>>> b'C\xc3N'.decode('utf8','replace')
C�N
os.walk
は、バイト文字列を取ることもでき、Unicode文字列の代わりにバイト文字列を返します。
for p,d,f in os.walk(b'.'):
その後、好きなようにデコードできます。
私はバイト文字列をos.walk()
に渡すことになりました。
for root, dirs, files in os.walk(b'.'):
print(root)
sed
またはgrep
でフィルターする:
set | sed -n '/^[a-zA-Z0-9_]*=/p'
# ... or ...
set | grep '^[a-zA-Z0-9_]*='
# ... or ...
set | egrep '^[_[:alnum:]]+='
これは、変数名がどれほど狂っているかに敏感です。最後のバージョンはほとんどのクレイジーなものを処理するはずです。