Как правильно перекодировать имена файлов (UTF-8)

Столкнулись с проблемой в использовании Far? Здесь можно получить помощь.
User avatar
SlashNet
Posts: 638
Joined: Fri 20 Mar, 2009 09:43
Location: Львов
Has thanked: 16 times
Been thanked: 16 times

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by SlashNet »

Latest post of the previous page:

John Doe wrote:Спотыкается на Ελληνικά.flv

Code: Select all

╬Х╬╗╬╗╬╖╬╜╬╣╬║╬м.flv
Но это допустим редко встречается, а вот ситуация когда нормальные имена вперемешку UTF-8, причём некорые UTF-8 битые - чаще.
В идеале надо бы чтоб переименование производилось только в случае удачного декодирования, а всё что не удалось переименовать - выводилось бы на консоль.
На батнике, я думаю, такое реально, но слишком муторно получится.
Это наверное легче будет скрипт написать на vbs, js, или PowerShell.
ədиw wo⊥є ʚ o⊥ʎнdəʚədəu əɔʚ
User avatar
SlashNet
Posts: 638
Joined: Fri 20 Mar, 2009 09:43
Location: Львов
Has thanked: 16 times
Been thanked: 16 times

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by SlashNet »

ədиw wo⊥є ʚ o⊥ʎнdəʚədəu əɔʚ
MDM
Posts: 90
Joined: Fri 02 Dec, 2005 20:47
Location: Москва
Has thanked: 4 times
Been thanked: 2 times

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by MDM »

В 7-ке работает такой вариант перекодировки, в 65001.txt просто "йцукен" в utf-8:

Code: Select all

@echo off
setlocal
1>nul chcp 65001

for /f %%i in (65001.txt) do call:convert %%i
1>nul chcp 866
goto:eof

:convert
1>nul chcp 866
1>866.txt echo %1
1>nul chcp 65001
XP с 65001 работает плохо, только из консоли, а батники в пролете. Так что лучше iconv
И еще заметил, что файлы UTF-8, созданные в блокноте отличаются от созданных другими способами.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by DV »

Как вариант: берём программу Renamer (http://www.den4b.com/?x=products&product=renamer) и в качестве правила переименования выбираем PascalScript со следующим кодом:

Code: Select all

var
  S: String;

begin
  S := WideToAnsi(FileName);
  FileName := UTF8Decode(S);
end.
User avatar
John Doe
Бюрократ
Posts: 13861
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by John Doe »

Прилагаемая утилита конвертирует содержимое, но не имена.
DV wrote:Как вариант: берём программу Renamer
Не нашёл там функции WideToOEM... Или это можно как-то иначе сделать?
User avatar
SlashNet
Posts: 638
Joined: Fri 20 Mar, 2009 09:43
Location: Львов
Has thanked: 16 times
Been thanked: 16 times

Посоветуйте правильный способ исправить имена файлов (UT

Post by SlashNet »

Прилагаемая утилита конвертирует содержимое, но не имена.
Вот блин. Недоглядел. WDX-плагин ведь как раз переименовывает. :pardon:
ədиw wo⊥є ʚ o⊥ʎнdəʚədəu əɔʚ
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Посоветуйте правильный способ исправить имена файлов (UT

Post by DV »

John Doe wrote:Не нашёл там функции WideToOEM... Или это можно как-то иначе сделать?
Таки нету...
Преобразование cp1251->cp866 можно попробовать через вызов внешней программы (см. ExecConsoleApp) ... Но навскидку написать такую программу не получилось (надо учитывать нюансы, что консольная программа может ожидать имя входного файла как cp866, так и cp1251, и точно так же её вывод может быть как cp866, так и cp1251).
User avatar
Centaur
Posts: 1083
Joined: Tue 05 Apr, 2005 20:09
Location: Novosibirsk, Russia
Been thanked: 2 times

Посоветуйте правильный способ исправить имена файлов (UT

Post by Centaur »

DV wrote:(надо учитывать нюансы, что консольная программа может ожидать имя входного файла как cp866, так и cp1251, и точно так же её вывод может быть как cp866, так и cp1251).
Не надо учитывать такие нюансы. Надо сразу писать так, чтобы имя входного файла было в юникоде, и вывод писать в юникоде.
User avatar
SlashNet
Posts: 638
Joined: Fri 20 Mar, 2009 09:43
Location: Львов
Has thanked: 16 times
Been thanked: 16 times

Посоветуйте правильный способ исправить имена файлов (UT

Post by SlashNet »

DecodeFilename wrote:

Code: Select all

Renames HTML encoded files.

DecodeFileName [/s] [/q] [/u] [/b] [/x] [match]

  match Specifies the wildcard to rename multiple files.
  /s Rename matching HTML encoded filenames from all subdirectories.
  /q Quiet mode, do not show the folders and renamed filenames.
  /u Create UndoDecodeFileName.cmd batch file to undo renaming later.
  /b Create DecodeFileName.cmd batch file rather than renaming files now.
  /x Simulation only, do no rename any files.

If no parameters are specified, then DecodeFileName will immediately rename any HTML encoded filenames in the current directory only.
Переименовывает файлы из: Downloded%20%22file%22.txt в Downloaded "file".txt
Last edited by SlashNet on Thu 01 Jan, 1970 01:00, edited 0 times in total.
Reason: [code], [spoiler]
ədиw wo⊥є ʚ o⊥ʎнdəʚədəu əɔʚ
User avatar
John Doe
Бюрократ
Posts: 13861
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by John Doe »

Только исправьте пример на Downloaded%20%22file%22.txt (иначе получается Downloded 4file4.txt).

Жаль что Unicode Wizard заброшен, очень подходил для подобных целей.

P.S.
Сам для этих целей использую плагин frename + любой онлайновый сервис.
Но frename конечно не умеет рекурсивно, поэтому приходилось делать батничек из dir/s/b.
User avatar
SlashNet
Posts: 638
Joined: Fri 20 Mar, 2009 09:43
Location: Львов
Has thanked: 16 times
Been thanked: 16 times

Re: Посоветуйте правильный способ исправить имена файлов (UT

Post by SlashNet »

John Doe wrote:Что-то тут не так: получается Downloded 4file4.txt
Скопипастил с офсайта.

А для переименовывания я пользую самописный python-скрипт.
Если кому интересно, то скрипт преобразовывает так: URL encoded -> UTF encoded -> ANSI (будьте осторожны с нерусским Юникодом)
Запускаю из Юзер Меню так:

Code: Select all

macro:post CtrlG $Text "C:\\Progra~1\\Far\\ConsTools\\Tools\\PythScripts\\cnvfnamu.py \"\x21.\x21\"" Enter
Из FunС%8FнезнаС%8Ekoff12%sale.txt получается следующее Funянезнаюkoff12%sale.txt
Attachments
cnvfnamu.py.zip
(1.1 KiB) Downloaded 177 times
ədиw wo⊥є ʚ o⊥ʎнdəʚədəu əɔʚ
User avatar
John Doe
Бюрократ
Posts: 13861
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Как правильно перекодировать имена файлов (UTF-8)

Post by John Doe »

Исходная задача решается в LuaFAR так:

Code: Select all

local utf8=[[╬Х╬╗╬╗╬╖╬╜╬╣╬║╬м]]
local utf16 = win.Utf8ToUtf16(utf8)
local cp866 = win.WideCharToMultiByte (utf16,866)
far.Show(cp866)
Last edited by HaRT on Thu 04 Feb, 2016 13:25, edited 1 time in total.
Reason: [code]
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Как правильно перекодировать имена файлов (UTF-8)

Post by DV »

Хорошо, что мне опять попалась на глаза эта тема!
Я ведь некоторое время назад даже специальную утилитку на C написал, чтобы использовать её в таких случаях:


Обновлено: теперь утилита сама (автоматически) определяет, является ли имя файла ANSI или OEM представлением последовательности UTF-8.
TheDrive
Posts: 8
Joined: Thu 04 Dec, 2014 00:19
Has thanked: 1 time
Been thanked: 1 time

Как правильно перекодировать имена файлов (UTF-8)

Post by TheDrive »

DecodeFileName неплохо работает, но игнорирует ИМЕНА папок. В сами папки заходит (при наличии ключа /s), но их имена игнорирует.
Переименовывает он только файлы с "процентами" в именах - URLEncoded, просто UTF-8 не трогает.
Утилита от DV deutf8.c наоборот, трогает имена UTF-8, но не трогает URLEncoded. Работает тоже хорошо.
Добавлю бинарник в аттач для тех, кому некогда заморачиваться с компиляцией.
deutf8_win32.zip
(1.9 KiB) Downloaded 126 times
Обе утилиты консольные. Не плагин, но всеж куда удобнее без "лишних движений мышкой" при работе из-под FAR.

Обе задачи сразу решаются в рамках Renamer.
Скрипт от DV решает проблему с именами UTF-8,
А следующий скрипт от Denis Kozlov, найденный на den4b.com,
решает проблему с именами URLEncoded

Code: Select all

function URLDecode(const S: AnsiString; out Output: AnsiString): Boolean;
var
  Idx: Integer;   // loops thru chars in string
  Hex: string;    // string of hex characters
  Code: Integer;  // hex character code (-1 on error)
begin
  // Intialise result and string index
  Result := False;
  Output := '';
  Idx := 1;
  // Loop thru string decoding each character
  while Idx <= Length(S) do
  begin
    case S[Idx] of
      '%':
      begin
        // % should be followed by two hex digits - exception otherwise
        if Idx <= Length(S) - 2 then
        begin
          // there are sufficient digits - try to decode hex digits
          Hex := S[Idx+1] + S[Idx+2];
          Code := StrToIntDef('$' + Hex, -1);
          Idx := Idx + 2;
        end
        else
          // insufficient digits - error
          Code := -1;
        // check for error and raise exception if found
        if Code = -1 then Exit;
        // decoded OK - add character to result
        Output := Output + Chr(Code);
      end;
      '+':
        // + is decoded as a space
        Output := Output + ' '
      else
        // All other characters pass thru unchanged
        Output := Output + S[Idx];
    end;
    Inc(Idx);
  end;
  Result := True;
end;
 
var
  Encoded, Decoded: AnsiString;
 
begin
  Encoded := WideToAnsi(FileName);
  if URLDecode(Encoded, Decoded) then
    FileName := UTF8Decode(Decoded)
  else
    FileName := '***ERROR***';
end.
Ради одного файла, конечно, запускать Renamer и долго тыкать мышкой все настраивая весьма избыточные затраты времени. но если файлов много, то можно все переименовать за 1-2 прохода.

Варианты URLEncode, кстати бывают разные
http://www.php.su/urlencode%28%29
Стандартный вариант регламентируется RFC1738.
Есть вариант, где пробелы "традиционно" заменяются на + (плюсы).
Post Reply

Return to “Нужна помощь”