Python: Как переместить файл с именем файла Unicode в папку Unicode - PullRequest
7 голосов
/ 02 апреля 2011

У меня чертовски много дела с перемещением файла с именем Unicode между папками с именем Unicode в скрипте Python под Windows ...

Какой синтаксис вы бы использовали, чтобы найти все файлы типа * .ext в папке и переместить их в относительное местоположение?

Предположим, что файлы и папки имеют Unicode.

Ответы [ 2 ]

15 голосов
/ 02 апреля 2011

Основная проблема заключается в непревращенном соединении между Unicode и байтовыми строками.Решения могут быть преобразованы в единый формат или избежать проблем, используя некоторые хитрости.Все мои решения включают стандартную библиотеку glob и shutil.

Для примера, у меня есть несколько имен файлов Unicode, заканчивающихся на ods, и я хочу переместить их в подкаталог с именем א (иврит алеф, символ Юникода).

Первое решение - указать имя каталога в виде байтовой строки:

>>> import glob
>>> import shutil
>>> files=glob.glob('*.ods')      # List of Byte string file names
>>> for file in files:
...     shutil.copy2(file, 'א')   # Byte string directory name
... 

Второе решение - преобразовать имена файлов в Unicode:

>>> import glob
>>> import shutil
>>> files=glob.glob(u'*.ods')     # List of Unicode file names
>>> for file in files:
...     shutil.copy2(file, u'א')  # Unicode directory name

Кредит Ezio Melotti, Список ошибок Python .

Третье решение - избегать назначения целевого имени каталога Unicode

Хотя это не лучшее решение вНа мой взгляд, здесь есть хороший трюк, о котором стоит упомянуть.

Измените каталог на каталог назначения с помощью os.getcwd(), а затем скопируйте в него файлы, указав его как .:

# -*- coding: utf-8 -*-
import os
import shutil
import glob

os.chdir('א')                   # CD to the destination Unicode directory
print os.getcwd()               # DEBUG: Make sure you're in the right place
files=glob.glob('../*.ods')     # List of Byte string file names
for file in files:
        shutil.copy2(file, '.') # Copy each file
# Don't forget to go back to the original directory here, if it matters

Более подробное объяснение

Простой подход shutil.copy2(src, dest) терпит неудачу, потому что shutil объединяет Unicode со строкой ASCII без преобразований:

>>> files=glob.glob('*.ods')
>>> for file in files:
...     shutil.copy2(file, u'א')
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python2.6/shutil.py", line 98, in copy2
    dst = os.path.join(dst, os.path.basename(src))
  File "/usr/lib/python2.6/posixpath.py", line 70, in join
    path += '/' + b
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 1: 
                    ordinal not in range(128)

Как было показано ранее, этого можно избежать при использовании 'א' вместо Unicode u'א'

Это ошибка?

На мой взгляд, это ошибка, потому что Python не может ожидать, что basedir имена будут всегда str, а не unicode сообщил об этом как о проблеме в баглисте Python , и жду ответов.

Дополнительная информация

Официальный Unicode Python HOWTO

3 голосов
/ 02 апреля 2011

Используйте строку Unicode везде:

# -*- coding: utf-8 -*-
# source code ^^ encoding; it might be different from sys.getfilesystemencoding()
import glob
import os

srcdir = u'مصدر الدليل' # <-- unicode string
dstdir = os.path.join('..', u'κατάλογο προορισμού') # relative path
for path in glob.glob(os.path.join(srcdir, u'*.ext')):
    newpath = os.path.join(dstdir, os.path.basename(path))
    os.rename(path, newpath) # move file or directory; assume the same filesystem

В движущихся файлах много тонких деталей;см. shutit.copy* функции.Вы можете использовать тот, который подходит в вашем конкретном случае, и успешно удалить исходные файлы, например, через os.remove().

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