On 2017-08-31 13:26, Peter Otten <__peter__@web.de> wrote:
Hermann Riemann wrote:
Allerdings fällt mir bei der Gelegenheit ein, was ist, wenn der Dateiname ein bytestring ist, der sich nicht nach utf konvertieren lässt? In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
Unter Linux kein Problem:
import os ord("/") 47 filename = bytes(c for c in range(1, 256) if c != 47) filename b'\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' os.path.exists(filename) False with open(filename, "w") as f: f.write("yadda\n") ... 6 os.path.exists(filename) True os.listdir() ['\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff']
Hier sieht man, was mit nicht dekodierbaren Bytes geschieht -- Python verwendet den surrogate-escape error handler:
b"\xf1\xf2\xf3".decode("utf-8", "surrogateescape") '\udcf1\udcf2\udcf3'
Die Shell kann da nicht mithalten:
[2]+ Angehalten python3 $ ls ??????????????????????????????? !"#$%&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Die Shell ist da gar nicht beteiligt. Die ruft ja nur "ls" auf. Der Output, den Du da zitierst, stammt von ls, und das ersetzt per default in der Ausgabe nicht-druckbare Zeichen durch "?" (das ist ein Feature - man will in einem Terminal nicht, das ls irgendwelche Escape-Codes ausgeben kann, nur weil der Ersteller eines Files lustig war). Es gibt Optionen, um die Ausgabe zu ändern, z.B. auf (oktale) Escape-Codes: % ls -b \001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\ !"#$%&'()*+,-.0123456789:;<\=\>?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{\|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377 Die Shell (zumindest die zsh, und ich nehme an, die bash auch nicht), hat kein Problem mit solchen Filenamen: % rm $'\001'$'\002'$'\003'$'\004'$'\005'$'\006'$'\a'$'\b'$'\t'$'\n'$'\v'$'\f'$'\r'$'\016'$'\017'$'\020'$'\021'$'\022'$'\023'$'\024'$'\025'$'\026'$'\027'$'\030'$'\031'$'\032'$'\033'$'\034'$'\035'$'\036'$'\037'\ \!\"\#\$%\&\'\(\)\*+,-.0123456789:\;\<=\>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]\^_\`abcdefghijklmnopqrstuvwxyz\{\|\}\~$'\177'$'\200'$'\201'$'\202'$'\203'$'\204'$'\205'$'\206'$'\207'$'\210'$'\211'$'\212'$'\213'$'\214'$'\215'$'\216'$'\217'$'\220'$'\221'$'\222'$'\223'$'\224'$'\225'$'\226'$'\227'$'\230'$'\231'$'\232'$'\233'$'\234'$'\235'$'\236'$'\237'$'\240'$'\241'$'\242'$'\243'$'\244'$'\245'$'\246'$'\247'$'\250'$'\251'$'\252'$'\253'$'\254'$'\255'$'\256'$'\257'$'\260'$'\261'$'\262'$'\263'$'\264'$'\265'$'\266'$'\267'$'\270'$'\271'$'\272'$'\273'$'\274'$'\275'$'\276'$'\277'$'\300'$'\301'$'\302'$'\303'$'\304'$'\305'$'\306'$'\307'$'\310'$'\311'$'\312'$'\313'$'\314'$'\315'$'\316'$'\317'$'\320'$'\321'$'\322'$'\323'$'\324'$'\325'$'\326'$'\327'$'\330'$'\331'$'\332'$'\333'$'\334'$'\335'$'\336'$'\337'$'\340'$'\341'$'\342'$'\343'$'\344'$'\345'$'\346'$'\347'$'\350'$'\351'$'\352'$'\353'$'\354'$'\355'$'\356'$'\357'$'\360'$'\361'$'\362'$'\363'$'\364'$'\365'$'\366'$'\367'$'\370'$'\371'$'\372'$'\373'$'\374'$'\375'$'\376'$'\377' (ich habe da einfach rm<space><tab> getippt, und die Expansion des Namens, den ich nicht tippen will, der Shell überlassen) Und weg is: % ls %
Unter Windows sind die Regeln wohl etwas komplexer.
Ja. Einerseits, weil es mehr reservierte Zeichen gibt, die entweder gar nicht oder nur an bestimmten Stellen vorkommen dürfen. Andererseits, weil Filenamen in NTFS keine Byte-Strings sind, sondern UTF-16-Strings. hp -- _ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung: |_|_) | | Man feilt solange an seinen Text um, bis | | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr __/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel