Как удалить папку с именами файлов символов Юникода, используя Perl rmtree?

У меня есть код Perl, который удаляет папки с помощью функции File::Path::rmtree. Эта функция работает успешно, если структура папок содержит файлы/папки с символами ascii, но не работает, если папка содержит файлы/папки с символами Unicode. Версия Perl, которую я использую: «Это perl 5, версия 12, subversion 4 (v5.12.4), построенная для MSWin32-x86-многопоточность"

Я также пытался использовать последнюю версию Perl, но проблема не устранена. Вот пример кода:

use strict 'vars';
require File::Path;

sub Rmdir($)
{
   my ($Arena) = "D:\\tmp\\TestUnicodeRm";

   if (-d $Arena){
   print "Dir to Rmtree $Arena\n";
       File::Path::rmtree($Arena,0,0);
}

     if (-d $Arena){
        print "Failed to clean up test area $Arena.\n";
     }
}

Rmdir $0;

1;

Если в каталоге «D:\tmp\TestUnicodeRm» есть файл с именем, скажем, «chinese_trad_我的文件.txt», тогда я получаю сообщение об ошибке «невозможно удалить каталог для XXX: каталог не пуст в строке D:\tmp\rmtree.pm ХХ".

Заранее спасибо!

См. также В какой кодировке readdir возвращает имя файла?

Håkon Hægland 10.04.2019 18:59

@ Håkon Hægland, большая часть ответа на связанный вопрос не применима, потому что он специфичен для Unix.

ikegami 11.04.2019 08:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
274
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Имена файлов всегда байты. К сожалению, нет указания или требования, чтобы символы Юникода в именах файлов были представлены в определенной кодировке, и каждая ОС имеет разные соглашения. В большинстве Unix-подобных систем имена файлов кодируются в UTF-8 и взаимодействуют с ними как с байтами. Однако в Windows имена файлов хранятся как UTF-16, но взаимодействуют с ними как с декодированными символами. Похоже на ошибку в File::Path, которая неправильно обрабатывает эти имена файлов по мере их нахождения - поскольку вы не предоставляете имена файлов, это не может быть ошибкой в ​​​​вашем коде.

Сначала я бы предложил убедиться, что ваш File::Path является последней версией (2.16). Если это не сработает, все, что я могу предложить, это сообщить об ошибке и либо вручную рекурсивно использовать opendir и readdir для удаления файлов и подкаталогов, либо раскошелиться на об/с.

my $rc = system 'rd', '/s', $dir; # check for errors as in system() docs

Re "Имена файлов всегда байты", Не в Windows. Там это строки 16-битных значений. /// Относительно "нет указания или требования, чтобы символы Юникода в именах файлов были представлены в определенной кодировке". В Windows имена файлов кодируются с использованием UTF-16le и поэтому должны кодироваться с использованием этой кодировки. /// Re "но взаимодействовал с декодированными символами", Как раз наоборот. Perl использует вызовы, которые ожидают/возвращают имя файла, закодированное с использованием системного ACP. /// Re "Похоже на ошибку в File::Path, это известная ошибка/ограничение функций Perl, которое просто наследуется File::Path.

ikegami 11.04.2019 04:34

@Grinnz Спасибо за ваш комментарий. Я пробовал с File::Path версии 2.15, и он все еще терпел неудачу. Мы используем 'rd'/'rmdir' в качестве альтернативного решения, но мы хотели избежать этого и вместо этого использовать некоторую реализацию lib/module.

user3406792 12.04.2019 12:43
Ответ принят как подходящий

Вы можете использовать сабвуферы, предоставленные Win32::Unicode::Файл и Win32::Unicode::Каталог, чтобы делать то, что вы хотите.


Windows предоставляет две версии каждого вызова API, который принимает или возвращает текст.

  • Версии с суффиксом «A» (ANSI) ожидают и возвращают текст, закодированный с использованием активной кодовой страницы системы. ("cp".Win32::GetACP() предоставляет имя кодировки, которое вы можете использовать с сабвуферами, предоставленными Encode.)

    Например, системный вызов DeleteFileA используется для удаления файла, и он ожидает путь, закодированный с использованием активной кодовой страницы системы.

  • Версии с суффиксом "W" (широкий) ожидают и возвращают текст, закодированный с использованием UTF-16le.

    Например, системный вызов DeleteFileW используется для удаления файла и ожидает путь, закодированный с использованием UTF-16le.

Perl использует версию «A» всех системных вызовов. Здесь требуется версия "W".

Упомянутые выше модули обеспечивают доступ к нужной вам версии "W" звонков.

Принято как ответ, так как это выглядит наиболее точным для моего требования. Однако мне не удалось собрать модуль на моей машине, поэтому я не смог его протестировать. Я попробую еще раз, как только у меня будет свободное время.

user3406792 13.04.2019 18:27

Другие вопросы по теме