Обработка обратной косой черты в именах файлов, прочитанных из файла - PullRequest
0 голосов
/ 09 сентября 2018

TL; DR : текстовый файл содержит строки, представляющие escape-символы обратной косой черты; как использовать их в качестве входных данных для os.stat()?

У меня есть входной файл input.txt:

./with\backspace
./with\nnewline

Обработка их с помощью простого цикла не работает:

>>> import os
>>> with open('input.txt') as f:
...     for line in f:
...         os.stat(line.strip())
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
FileNotFoundError: [Errno 2] No such file or directory: './with\\backspace'

Использование .decode("unicode_escape"), как предложено в , другой вопрос работает только частично - первая строка в файле терпит неудачу, вторая с \n не работает.


Sidenote: входные имена файлов имеют ./, и я знаю, что могу просто использовать os.listdir('.') и перебирать файлы, пока не найду правильные. Это не моя цель. Целью является обработка имен файлов, которые содержат экранирование от обратной косой черты из файла.


Дополнительный тест:

>>> import os
>>> with open('./input.txt') as f:
...     for l in f:
...         os.stat(l.strip().decode('unicode_escape'))
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
AttributeError: 'str' object has no attribute 'decode'
>>> with open('./input.txt') as f:
...     for l in f:
...         try:
...             os.stat(l.strip().encode('utf-8').decode('unicode_escape'))
...             print(l.strip())
...         except:
...             pass
... 
os.stat_result(st_mode=33188, st_ino=1053469, st_dev=2049, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1536468565, st_mtime=1536468565, st_ctime=1536468565)
./with\nnewline

Написание явной строки с os.fsencode() работает:

>>> os.stat(os.fsencode('with\x08ackspace'))
os.stat_result(st_mode=33188, st_ino=1053465, st_dev=2049, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1536468565, st_mtime=1536468565, st_ctime=1536468565)

Однако, с несколькими вариантами выполнения одной и той же команды, я все еще не могу прочитать строку из файла, так что os.stat() принимает ее.

>>> with open('./input.txt') as f:
...      for l in f:
...          os.stat(os.fsdecode( bytes(l.strip(),'utf-8').decode('unicode_escape').encode('latin1') ) )
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
FileNotFoundError: [Errno 2] No such file or directory: './with\x08ackslash'

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Через 2 часа после этого я понял, что входной файл содержит ./with\backslash, а фактическое имя файла создается с помощью touch with$'\b'ackspace.Таким образом, Health Raftery's answer работает, но только для Python 2. В Python 3 вы получаете AttributeError: 'str' object has no attribute 'decode', поскольку строка в Python 3 уже является строкой Unicode .

Inпроцесс, возможно, я нашел лучший подход через os.fsencode () , указанный в ответе jfs .

import os

with open('./input.txt') as f:
    for l in f:
        # alternatively one can use 
        # bytes(l.strip(),sys.getdefaultencoding())
        bytes_filename =  bytes(l.strip(), 'utf-8').decode('unicode_escape')
        f_stat = os.stat(os.fsdecode( bytes_filename ) )
        print(l.strip(),f_stat)

Поскольку я использую в основном Python 3, этоэто то, что я искал.Тем не менее, Ответ Здоровья Рафтери , тем не менее, действителен, следовательно, +1.

0 голосов
/ 09 сентября 2018

Работает в macos:

touch $'with\backspace'
touch $'with\newline'
echo $'./with\\backspace\n./with\\newline' > input.txt
python
>>> import os
>>> with open('./input.txt') as f:
...     for l in f:
...         os.stat(l.strip().decode('unicode_escape'))
posix.stat_result(st_mode=33188, st_ino=8604304962, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=0, st_atime=1536469815, st_mtime=1536469815, st_ctime=1536469815)
posix.stat_result(st_mode=33188, st_ino=8604305024, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=0, st_atime=1536470112, st_mtime=1536470112, st_ctime=1536470112)

Это с Python 2.7.14 в Darwin Kernel версии 17.7.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...