2

Недавно я попытался объяснить другу, как создать простой командный файл в одну строку:

subst t: "X:\Example"

На моей машине, которая хорошо работала в течение многих лет, но с их я столкнулся с проблемой: их имя содержало не-ASCII символы (точнее турецкие символы ı и ç), которые не были распознаны должным образом.

Простое решение этого, которое я хотел бы добавить

chcp 65001

в верхней части файла, чтобы изменить активную кодовую страницу на UTF-8.

Но это не сработало. На их компьютере это вызвало сбой командной оболочки, которая его выполняла. Я заставил их попробовать несколько разных значений; Сбой 65000, но не 10000, и все значения ниже того, что я пробовал, также работали, но они не соответствовали тем же кодовым страницам, что и те же значения на моем компьютере. Их кодовая страница по умолчанию также отличалась (857 вместо 850, как на моем компьютере). Это имеет смысл, поскольку, согласно MSDN, 857 - это турецкая кодовая страница, а 850 - западноевропейская).

Я знаю, что некоторые кодовые страницы могут изменяться с компьютера на компьютер, но на странице MSDN прямо говорится, что следует использовать UTF-8, потому что другие страницы могут измениться (хотя есть печальная нехватка документации относительно того, как и когда они изменяются).

Это ложно? Может ли значение 65001 измениться? Если это так, то почему это может привести к сбою? Разве это не должно жаловаться на "Неверную кодовую страницу" в худшем случае? И если это действительно изменится, как можно узнать, какое значение использовать, чтобы получить его, или как еще можно заставить его принимать символы, не входящие в ASCII?

Я использую Windows 10 с английским языком (он был предустановлен с Windows 8.1 итальянский), в то время как мой друг использует Windows 7 турецкий.

1 ответ1

2

В основном, Windows cmd (и его интерпретатор пакетных сценариев) зависит от соответствия (текущей) активной кодовой страницы и кодировки пакетных сценариев. Например, если вы сохраняете сценарий из Notepad в так называемой кодировке ANSI (что сильно зависит от языкового стандарта системы Windows), вам следует запустить его в соответствующей кодовой странице, см. Справочник по API поддержки национальных языков (NLS):

  • English (US) : ANSI соответствует ACP 1252 (CP 437),
  • English (UK) : ANSI соответствует ACP 1252 (CP 850),
  • Turkish : ANSI соответствует ACP 1254 (CP 857),
  • Central Europe: ANSI соответствует ACP 1250 (CP 852) и т.д.

Ваше предположение верно:

Простое решение этого - добавить в начало файла chcp 65001 чтобы заменить активную кодовую страницу на UTF-8. ... Но это не сработало.

К сожалению, ни Windows cmd ни пакетный интерпретатор не заботятся о значении байтового порядка и рассматривают его как допустимый символ - независимо от текущей активной кодовой страницы.
Следовательно, первая строка (CHCP 65001 в вашем случае) файла в кодировке UTF-8 загрязняется, если присутствует спецификация; попытка выполнить такую грязную команду приведет к тому, что сообщение об ошибке ' CHCP' is not recognized as an internal or external command, operable program or batch file (уровень ошибки 9009).

Решение: сохраните свой сценарий в кодировке UTF-8 без спецификации.
Обходной путь, если вы не можете сделать это (так как Notepad всегда пишет BOM): используйте пустую команду в качестве первой строки вашего скрипта, например, следующим образом:

@rem if this line is visibly executed then BOM is present >NUL 2>&1
@echo OFF
    rem save current code page to the `_chcp` variable
for /F "tokens=2 delims=:" %%G in ('chcp') do set "_chcp=%%G"
    rem change active code page to UTF-8 (silently)
CHCP 65001 >NUL
    rem echo this is UTF-8 encoded batch file %~nx0
echo(
subst t: "D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ"
subst
dir /B /S t:\*.txt
subst t: /D
echo(
echo(  works as well for characters from Unicode Basic Multilingual Plane
subst t: "D:\bat\Unusual Names\CJK\中文(繁體)"
subst
dir /B /S t:\*.txt
subst t: /D
echo(
echo(  works even for characters from Unicode Supplementary Multilingual Plane
subst t: "D:\bat\Unusual Names\"
subst
dir /B /S t:\*.txt
subst t: /D
    rem set active code page back to previously saved value (verbose)
echo(
CHCP %_chcp%

Выход:

==> utf8.bat

==> ´╗┐@rem if this line is visibly executed then BOM is present  1>NUL 2>&1

T:\: => D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ
t:\ĞÜİŞÇÖçğüşöı.txt

  works as well for characters from Unicode Basic Multilingual Plane
T:\: => D:\bat\Unusual Names\CJK\中文(繁體)
t:\chinese traditional.txt

  works even for characters from Unicode Supplementary Multilingual Plane
T:\: => D:\bat\Unusual Names\
t:\Mathematical Bold Script.txt

Active code page: 852

Наконец, вы можете удалить первую строку (содержащую BOM) из вашего скрипта, используя команду more следующим образом (перед запуском chcp 65001 обратите внимание на more +1 …):

==> chcp 65001
Active code page: 65001

==> more +1 utf8.bat > utf8noBOM.bat

==> utf8noBOM.bat

T:\: => D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ
t:\ĞÜİŞÇÖçğüşöı.txt

  works as well for characters from Unicode Basic Multilingual Plane
T:\: => D:\bat\Unusual Names\CJK\中文(繁體)
t:\chinese traditional.txt

  works even for characters from Unicode Supplementary Multilingual Plane
T:\: => D:\bat\Unusual Names\
t:\Mathematical Bold Script.txt

Active code page: 65001

==>

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .