Вывод в файл cmd кодировка

Команда CHCP используется для просмотра или изменения текущей кодовой страницы в окне командной строки Windows. Кодовая страница (Code Page или сокращенно CP) определяет соответствие между двоичным кодом и соответствующим ему символом, отображаемом на экране. Для кодирования текстов на русском языке (то есть букв кириллицы) наиболее широко применяются следующие кодовые страницы:

— Windows-1251, она же Microsoft code page 1251 (CP1251) в операционных системах семейства Windows;

— Кодовая страница CP866, она же IBM code page 866 — в операционных системах семейства DOS, а также в приложениях командной строки Microsoft Windows;

Стандартно, в приложениях командной строки, используется кодовая страница 866 , что соответствует DOS-кодировке. Окно приложения CMD.EXE запускается с установленной кодовой страницей 866 . Изменение кодовой страницы действует только по отношению к текущему сеансу CMD.

Примеры использования команды CHCP:

chcp — отобразить текущую кодовую страницу.

chcp 1251 — установить кодовую страницу, соответствующую Windows-кодировке.

chcp 866 — установить кодовую страницу, соответствующую DOS-кодировке.

При создании командных файлов, необходимо учитывать то обстоятельство, что текст на русском языке должен быть представлен в DOS-кодировке.

chcp 866; chcp 1251; chcp 65001 — не помогали.

Оказывается надо в свойствах самого cmd выбрать шрифт Lucida Console. Только так можно получить нормальный текст на русском языке.

Спасшая статья

Приложение cmd.exe – это командная строка или программная оболочка с текстовым интерфейсом (во загнул ).

Вывод в файл cmd кодировка

Если Вы занялись проблемой кодировки шрифтов в cmd.exe , то как запускать командную строку наверняка уже знаете

Перейдем собственно к проблеме: иногда вместо русских букв при выполнении команд выходит набор непонятных символов ( рис.2).

Вывод в файл cmd кодировка

Вывод в файл cmd кодировка

Теперь Вы получили нормальный текст на русском языке. Так же можно поменять текущую кодировку шрифта, для этого используется команда chcp. Набираем эту команду и жмем Enter, в результате получим текущую кодировку для командной строки – рис.4.

Вывод в файл cmd кодировка

Для изменения кодировки так же применим chcp в следующем формате:

Где – это цифровой параметр нужного шрифта, например,

1251 – Windows (кириллица);

Выбирайте на любой вкус. Т.о. что бы изменить кодировку на UTF-8 нужно выполнить команду chcp 65001.

Вывод в файл cmd кодировка

almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.

Вывод в файл cmd кодировка
Вывод в файл cmd кодировка
Вывод в файл cmd кодировка
Вывод в файл cmd кодировка
Вывод в файл cmd кодировка

Вывод в файл cmd кодировка

Как корректно отобразить Русский текст в CMD. Проблемы с кодировкой могут возникнуть, например, при выполнении Bat файла, когда нужно вывести в консоль русский текст и при других обстоятельствах, о которых речь пойдёт далее.

Рассмотрим пример: когда нужно вывести в консоль Русский текст, скажем «Примет мир». Для этого создадим Bat файл с именем «1.bat». Используйте для этого обычный Блокнот Windows (Notepad.exe) Запишем в него следующие строки!

Теперь запускаем файл 1.bat и результат будет такого вида.

Вывод в файл cmd кодировка

Как видим проблема с кодировкой в cmd на лицо. И произошло это по следующей причине.

Стандартный блокнот Windows сохранил Bat файл в кодировке «1251» а консоль вывела его в кодировки «866». Вот от сюда все проблемы!

Решения проблемы с кодировкой в CMD. 1 Способ.

Скачиваем и устанавливаем на свой компьютер «Notepad++».

После запуска «Notepad++» запишете в документ те же строки, которые мы уже ранние записывали в стандартный блокнот.

Теперь осталось сохранить документ с именем «2.bat» в правильной кодировке. Для этого идём в меню «Кодировки > Кодировки > Кириллица > OEM-866»

Вывод в файл cmd кодировка

и теперь сохраняем файл с именем «2.bat» и запускаем его! Поле запуска результат на лицо.

Вывод в файл cmd кодировка

Как видим, текст на Русском в CMD отобразился, как положено.

Решения проблемы с кодировкой в CMD. 2 Способ.

Теперь рассмотрим ещё одну ситуацию, когда могут возникнуть проблемы с кодировкой в CMD.

Допустим, ситуация требует сохранить результат выполнения той или иной команды в обычный «TXT» файл. В приделах этого поста возьмём для примера команду «HELP».

Задача : Сохранить справку CMD в файл «HelpCMD.txt. Для этого создайте Bat файл и запишите в него следующие строки.

После выполнения Bat файла в корне диска «C:» появится файл «HelpCMD.txt» и вместо справки получится вот что:

Вывод в файл cmd кодировка

Естественно, такой вариант не кому не понравится и что бы сохранить справку в понятном для человека виде, допишите в Bat файл строку.

Теперь содержимое кода будет такое.

После выполнения «Батника» результат будет такой:

Вывод в файл cmd кодировка

Вот так на много лучше, правда?

Пожалуй, на этом я закончу пост. Добавить больше нечего. Если у Вас имеются какие-то соображения по данной теме, буду рад Вашему комментарию к посту.

Дополнительно из комментариев то Garric

Автор очень хорошо описал принцип. ! Но это неудобно.
Нужно бы добавить. Если автор добавит это в статью то это будет Good.
Создаём файл .reg следующего содержания:
——
Windows Registry Editor Version 5.00

No, you can’t with pure redirection.
But with some tricks (like tee.bat) you can.

I try to explain the redirection a bit.

You redirect one of the ten streams with > file or < file
It is unimportant, if the redirection is before or after the command,
so these two lines are nearly the same.

dir > file.txt
> file.txt dir

The redirection in this example is only a shortcut for 1>, this means the stream 1 (STDOUT) will be redirected.
So you can redirect any stream with prepending the number like 2> err.txt and it is also allowed to redirect multiple streams in one line.

dir 1> files.txt 2> err.txt 3> nothing.txt

In this example the “standard output” will go into files.txt, all errors will be in err.txt and the stream3 will go into nothing.txt (DIR doesn’t use the stream 3).
Stream0 is STDIN
Stream1 is STDOUT
Stream2 is STDERR
Stream3-9 are not used

But what happens if you try to redirect the same stream multiple times?

dir > files.txt > two.txt

“There can be only one”, and it is always the last one!
So it is equal to dir > two.txt

Ok, there is one extra possibility, redirecting a stream to another stream.

dir 1>files.txt 2>&1 

2>&1 redirects stream2 to stream1 and 1>files.txt redirects all to files.txt.
The order is important here!

dir ... 1>nul 2>&1
dir ... 2>&1 1>nul

are different. The first one redirects all (STDOUT and STDERR) to NUL,
but the second line redirects the STDOUT to NUL and STDERR to the “empty” STDOUT.

As one conclusion, it is obvious why the examples of Otávio Décio and andynormancx can’t work.

command > file >&1
dir > file.txt >&2

Both try to redirect stream1 two times, but “There can be only one”, and it’s always the last one.
So you get

command 1>&1
dir 1>&2

And in the first sample redirecting of stream1 to stream1 is not allowed (and not very useful).

Rob van der Woude's Scripting Pages

Display & Redirect Output

On this page I’ll try to explain how redirection works.
To illustrate my story there are some examples you can try for yourself.

For an overview of redirection and piping, view my original redirection page.

Display text

ECHO Hello world
Hello world

When I say “on screen”, I’m actually referring to the “DOS Prompt”, “console” or “command window”, or whatever other “alias” is used.

Streams

The output we see in this window may all look alike, but it can actually be the result of 3 different “streams” of text, 3 “processes” that each send their text to thee same window.

Those of you familiar with one of the Unix/Linux shells probably know what these streams are:

  • Standard Output
  • Standard Error
  • Console

Standard Error is the stream where many (but not all) commands send their error messages.

And some, not many, commands send their output to the screen bypassing Standard Output and Standard Error, they use the Console.
By definition Console isn’t a stream.

There is another stream, Standard Input: many commands accept input at their Standard Input instead of directly from the keyboard.
Probably the most familiar example is MORE:

DIR /S | MORE

(Since MORE‘s Standard Input is used by DIR, MORE must catch its keyboard presses (the “Any Key”) directly from the keyboard buffer instead of from Standard Input.)

Redirection

You may be familiar with “redirection to NUL” to hide command output:

ECHO Hello world>NUL

will show nothing on screen.
That’s because >NUL redirects all Standard Output to the NUL device, which does nothing but discard it.

Now try this (note the typo):

EHCO Hello world>NUL
'EHCO' is not recognized as an internal or external command, operable program or batch file.

This is a fine demonstration of only Standard Output being redirected to the NUL device, but Standard Error still being displayed.

Redirecting Standard Error in “true” MS-DOS (COMMAND.COM) isn’t possible (actually it is, by using the CTTY command, but that would redirect all output including Console, and input, including keyboard).
In Windows NT 4 and later (CMD.EXE) and in OS/2 (also CMD.EXE) Standard Error can be redirected by using 2> instead of >

A short demonstration. Try this command:

ECHO Hello world 2>NUL

What you should get is:

Hello world

Now make a typo again:

EHCO Hello world 2>NUL

What did you get?
Nothing
That’s because the error message was sent to the Standard Error stream, which was in turn redirected to the NUL device by 2>NUL

When we use > to redirect Standard Output, CMD.EXE interprets this as 1>, as can be seen by writing and running this one-line batch file “test.bat”:

DIR > NUL

Now run test.bat in CMD.EXE and watch the result:

C:\>test.bat
C:\>DIR 1>NUL
C:\>

It looks like CMD.EXE uses 1 for Standard Output and 2 for Standard Error.
We’ll see how we can use this later.

@ECHO OFF
ECHO This text goes to Standard Output
ECHO This text goes to Standard Error 1>&2
ECHO This text goes to the Console>CON

Run test.bat in CMD.EXE, and this is what you’ll get:

C:\>test.bat
This text goes to Standard Output
This text goes to Standard Error
This text goes to the Console
C:\>

Now let’s see if we can separate the streams again.
Run:

test.bat > NUL

and you should see:

C:\>test.bat
This text goes to Standard Error
This text goes to the Console
C:\>

We redirected Standard Output to the NUL device, and what was left were Standard Error and Console.

test.bat 2> NUL

and you should see:

C:\>test.bat
This text goes to Standard Output
This text goes to the Console
C:\>

We redirected Standard Error to the NUL device, and what was left were Standard Output and Console.

:/>  Основные cmd команды – просто о полезном | Лайфхаки

Nothing new so far. But the next one is new:

test.bat > NUL 2>&1

and you should see:

C:\>test.bat
This text goes to the Console
C:\>

This time we redirected both Standard Output and Standard Error to the NUL device, and what was left was only Console.
It is said Console cannot be redirected, and I believe that’s true.
I can assure you I did try!

To get rid of screen output sent directly to the Console, either run the program in a separate window (using the START command), or clear the screen immediately afterwards (CLS).

In this case, we could also have used test.bat >NUL 2>NUL
This redirects Standard Output to the NUL device and Standard Error to the same NUL device.
With the NUL device that’s no problem, but when redirecting to a file one of the redirections will lock the file for the other redirection.
What 2>&1 does, is merge Standard Error into the Standard Output stream, so Standard output and Standard Error will continue as a single stream.

Redirect “all” output to a single file:

test.bat > test.txt 2>&1

and you’ll get this text on screen (we’ll never get rid of this line on screen, as it is sent to the Console and cannot be redirected):

This text goes to the Console
This text goes to Standard Output
This text goes to Standard Error

Redirect errors to a separate error log file:

test.bat > testlog.txt 2> testerrors.txt

and you’ll get this text on screen (we’ll never get rid of this line on screen, as it is sent to the Console and cannot be redirected):

This text goes to the Console
This text goes to Standard Output
This text goes to Standard Error

Nothing is impossible, not even redirecting the Console output.

Unfortunately, it can be done only in the old MS-DOS versions that came with a CTTY command.

The general idea was this:

CTTY NUL
ECHO Echo whatever you want, it won't be displayed on screen no matter what.
ECHO By the way, did I warn you that the keyboard doesn't work either?
ECHO I suppose that's why CTTY is no longer available on Windows systems.
ECHO The only way to get control over the computer again is a cold reboot,
ECHO or the following command:
CTTY CON

A pause or prompt for input before the CTTY CON command meant one had to press the reset button!

Besides being used for redirection to the NUL device, with CTTY COM1 the control could be passed on to a terminal on serial port COM1.

Escaping Redirection (not to be interpreted as “Avoiding Redirection”)

Redirection always uses the main or first command’s streams:

START command > logfile

will redirect START‘s Standard Output to logfile, not command‘s!
The result will be an empty logfile.

A workaround that may look a bit intimidating is grouping the command line and escaping the redirection:

START CMD.EXE /C ^(command ^> logfile^)

What this does is turn the part between parentheses into a “literal” (uninterpreted) string that is passed to the command interpreter of the newly started process, which then in turn does interpret it.
So the interpretation of the parenthesis and redirection is delayed, or deferred.

A safer way to redirect STARTed commands’ output would be to create and run a “wrapper” batch file that handles the redirection.
The batch file would look like this:

command > logfile

and the command line would be:

START batchfile

Some “best practices” when using redirection in batch files:

  • Use >filename.txt 2>&1 to merge Standard Output and Standard Error and redirect them together to a single file.
    Make sure you place the redirection “commands” in this order.
  • Use >logfile.txt 2>errorlog.txt to redirect success and error messages to separate log files.
  • Use >CON to send text to the screen, no matter what, even if the batch file’s output is redirected.
    This could be useful when prompting for input even if the batch file’s output is being redirected to a file.
  • Use 1>&2 to send text to Standard Error.
    This can be useful for error messages.
  • It’s ok to use spaces in redirection commands.
    Note however, that a space between an ECHO command and a > will be redirected too.
    DIR>filename.txt and DIR > filename.txt are identical, ECHO Hello world>filename.txt and ECHO Hello world > filename.txt are not, even though they are both valid.
    It is not ok to use spaces in >> or 2> or 2>&1 or 1>&2 (before or after is ok).
  • In Windows NT 4, early Windows 2000 versions, and OS/2 there used to be some ambiguity with ECHOed lines ending with a 1 or 2, immediately followed by a >:
    ECHO Hello world2>file.txt would result in an empty file file.txt and the text Hello world (without the trailing “2”) on screen (CMD.EXE would interpret it as ECHO Hello world 2>file.txt).
    In Windows XP the result is no text on screen and file.txt containing the line Hello world2, including the trailing “2” (CMD.EXE interprets it as ECHO Hello world2 >file.txt).
    To prevent this ambiguity, either use parentheses or insert an extra space yourself:
    ECHO Hello World2 >file.txt
    (ECHO Hello World2)>file.txt
  • “Merging” Standard Output and Standard Error with 2>&1 can also be used to pipe a command’s output to another command’s Standard Input:
    somecommand 2>&1 | someothercommand
  • Redirection overview page
  • Use the TEE command to display on screen and simultaneously redirect to file

page last modified: 2016-09-19

Мы все любим писать серьезные вещи на серьезных языках. Шаблоны, C++, Reflection, Perl и многое другое – вот то, что мы любим, то, чему посвящаем длинные сообщения в форумах, то, что снится нам по ночам.

К чему я это все? А к тому, что поговорим мы о полезных хитростях при написании файлов сценариев на встроенном командном языке Windows. К счастью, это занятие не является доминирующим в профессиональной деятельности автора, так что я не обязуюсь заполнить абсолютно все пробелы в данной области. Кроме того, рожденный ползать летать не может, и из cmd.exe, увы, не получится ни /usr/bin/perl, ни даже /bin/sh. Так что, все нижеприведенное – просто некоторые интересные факты из жизни файлов с расширением bat, на которые автор обратил внимание во время решения различных практических задач автоматизации.

ПРЕДУПРЕЖДЕНИЕ

Как экранировать символ?

В командном языке Windows существует некоторый набор символов с высоким приоритетом, которые всегда трактуются как спецсимволы. К ним, в частности, относятся:

  • Операторы перенаправления ввода-вывода <, >, >>.
  • Оператор конвейера |.
  • Операторы объединения команд ||, & и &&.
  • Оператор разыменования переменной %…%.

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

 The ratio should be up to %

символ процента будет «съеден» интерпретатором, который решит, что это попытка вывода значения какой-то переменной. В случае со знаком процента решение довольно хорошо известно и состоит в удвоении этого символа:

 The ratio should be up to %%

после чего все заработает так, как надо. Однако в других случаях все менее очевидно. Рассмотрим командный сценарий, который генерирует незатейливый HTML-файл:

@ <html> > <head> >> <title>This is a greeting page</title> >> </head> >> <body> >> Hello World! >> </body> >> </html> >>

К сожалению, при попытке запуска этого “чуда инженерного разума” нас постигнет неудача в виде сообщения об ошибке “was unexpected at this time”.

Оно и понятно: командный интерпретатор не в силах разобраться, где его просят вывести на экран символ HTML-тега, а где перенаправить вывод. В нормальных языках программирования эта проблема обычно решается обрамлением строковых литералов кавычками. Отчасти это помогает и в bat-файлах. Но лишь отчасти. Выполнение строки

 >

приведет к тому, что в выходной файл будут записаны и сами кавычки. Это явно не совсем то, что требуется.

К счастью, есть один малоизвестный способ, позволяющий добиться требуемого результата. Символ ^ позволяет экранировать любой другой символ с безусловным приоритетом. Таким образом, вышеприведенный пример генерации HTML может быть успешно записан так:

@ ^<html^> > ^<head^> >> ^<title^>This is a greeting page^</title^> >> ^</head^> >> ^<body^> >> Hello World! >> ^</body^> >> ^</html^> >>

Как перенести длинную строку?

Совет по поводу экранирующего символа ^ имеет еще одно применение: перенос строк. Я (как и многие из вас, наверное) люблю, чтобы любой исходный текст, который я пишу, выглядел красиво – даже *.bat-файлы. Одним из обязательных условий красоты и удобочитаемости кода для меня является его ширина: все строки должны умещаться в 78 столбцов. Можно поспорить по поводу числа 78, но в одном я непреклонен – ограничение на ширину текста кода должно быть, иначе это не код, а макароны.

Так вот долгое время *.bat-файлы портили мне жизнь тем, что иногда приходилось писать длинную строку – например, вызов какой-нибудь другой программы с кучей опций, и я не знал, что с этим делать. Происходило это нечасто, но всегда было неприятно. Но, к счастью, моя жизнь изменилась с тех пор, как я открыл для себя Супер-Символ ^:

packagebin.exe --recursive-searchyes --files-maskexe,dll,pdb,obj ^
--archive-typezip --archive-levelmax --deliver-methodftp ^
--deliver-targetftp://ftp.site.com

Помните лишь, что чудо-символ должен быть последним в строке – скажите «Нет!» концевым пробелам.

Как определить имя каталога, в котором находится запущенный командный файл?

Иногда сценарию надо знать полный путь к себе самому и/или к каталогу, в котором он находится. Это может понадобиться по разным причинам. Например, он должен достать из системы контроля версий исходники в каталог/src рядом с собой. Или, запускаются тесты из каталога/tests, и перед их запуском надо добавить каталог/bin в переменную PATH.

Можно, конечно, рассчитывать на то, что командный файл был вызван из того же каталога, где он находится, и тогда в качестве вышеупомянутогоможно использовать переменную окружения %CD% – полный путь к текущему каталогу. Однако любые допущения в нашем деле недопустимы (хороший каламбур, однако!). Поэтому приведу более надежное решение.

Прежде всего, вспоминаем, что переменная %0 в bat-файле соответствует нулевому аргументу командной строки, т.е. имени самого файла. После этого читаем скудную документацию для команды call:

и обнаруживаем, что при использовании нумерованных переменных %0-%9 можно использовать некоторые модификаторы:

%~1 – разворачивает %1, удаляя кавычки (“)
%~f1 – разворачивает %1 в полный квалифицированный путь
%~d1 – разворачивает %1 в букву диска
%~p1 – разворачивает %1 в путь
%~n1 – разворачивает %1 в имя файла
%~x1 – разворачивает %1 в расширение файла
%~s1 – развернутый путь будет содержать только короткие имена
%~a1 – разворачивает %1 в атрибуты файла
%~t1 – разворачивает %1 в дату/время создания файла
%~z1 – разворачивает %1 в размер файла
%~$PATH:1 – Ищет в каталогах, перечисленных в переменной среды PATH, и разворачивает %1 в полное квалифицированное имя первого совпадения. Если имя переменной среды не определено, или если файл не найден, этот модификатор вернет пустую строку и, более того, модификаторы можно объединять для получения сложных результатов:

%~dp1 - разворачивает %1 в букву диска и путь
%~nx1 - разворачивает %1 в имя файла с расширением
%~dp$PATH:1 – ищет %1 в каталогах, перечисленных в переменной среды PATH, и разворачивает в букву диска
и путь к первому найденному файлу.
%~ftza1 - разворачивает %1 в строку, подобную DIR

Таким образом, правильным будет использовать в качестве тега сочетание %~dp0, которое будет раскрыто в полный путь к каталогу, где находится сценарий. Например,

 --recursive-searchyes --files-maskexe,dll,pdb,obj ^
--archive-typezip --archive-levelmax --deliver-methodftp ^
--deliver-targetftp://ftp.site.com --deliver-source

Обратите внимание на использование кавычек – потенциально каталог может иметь в своем пути пробел. Кавычки избавят от проблем в этом случае.

:/>  Ключи для office 2016 | Бесплатно, активация [свежие]

ПРЕДУПРЕЖДЕНИЕ

Как получить короткое (8.3) имя файла?

ПРЕДУПРЕЖДЕНИЕ

Доступ к файлу по короткому имени может быть не всегда возможен. На файловой системе NTFS создание коротких псевдонимов для файлов может быть отключено путем установки в единицу значения «NtfsDisable8dot3NameCreation» в ключе реестра «HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem».

Итак, все же (в предположении, что надругательства над NTFS не было) – как? Внимательный читатель должен был заметить в предыдущем разделе, что при обращении к переменным %0 – %9 можно использовать префикс (расширенный путь будет содержать только короткие имена)

который нам как раз мог бы помочь. Но есть засада – все эти полезные префиксы нельзя использовать с произвольной переменной окружения, а присваивание переменным %0 – %9 не поддерживается. К счастью, описываемые префиксы можно еще использовать с переменными цикла for, и это дает нам способ достичь требуемого результата. Например, вот так можно получить 8.3-путь к “Program Files”:

 /d in () (
)
 .-имя для каталога -^> 

Как перенаправить стандартный вывод в файл?

Плоха та короткая программа, которая не стремится стать большой. К сожалению, это правило применимо и к командным файлам Windows тоже – иногда bat-файлы вырастают до довольно больших размеров. Если при этом результат выполняемых команд должен журналироваться, то все становится совсем плохо – почти каждая строка имеет хвостик типа

 Cleaning up the target directory >>
...
 The target directory has been cleaned >>
@ out.html ( yes
cmd.exe /c %* >
exit /b
) ^<html^>
echo ^<head^>
echo ^<title^>This is a greeting page^</title^> ^</head^> ^<body^>
echo Hello World! ^</body^> ^</html^>

Здесь делается то же, что и раньше, но с перенаправлением стандартного вывода в файл out.html. Делается это простым способом – перезапуском сценарием самого себя. Сначала проверяется, не установлена ли переменная окружения STDOUT_REDIRECTED. Если она установлена, значит, сценарий уже перезапущен с перенаправленным выводом и можно просто продолжить работу. Если же переменная не установлена, то мы ее устанавливаем и перезапускаем скрипт (cmd.exe /c %0) с таким же набором параметров, что и исходная команда (%*) и перенаправленным в файл стандартным выводом (>%OUTPUT%). После завершения выполнения «перенаправленной» команды выходим.

Как сложить два числа?

Краткий ответ – смотри:

Длинный ответ таков. В bat-файлах можно производить довольно-таки продвинутые вычисления – продвинутые не в сравнении с другими языками, а в сравнении с отсутствием возможности что-либо вычислить вообще. Вычисление осуществляется командой set, если она выполняется с ключом /a. Поддерживается практически полный набор операторов языка C, включая шестнадцатеричный модификатор 0x. Переменные окружения в выражении не обязательно заключать в знаки процента – все, что не является числом, считается переменной. Подробнее – все-таки в man set, тьфу, то есть в set /?. А здесь напоследок – просто несколько примеров.

@ 
 
 /a RESULTARG + 
 
 
rem Если выражение содержит какие-либо из символов non grata, надо
rem заключить его в кавычки
 /a RESULT"ARG << 2"
 
 
rem Шестнадцатеричная арифметика
 /a RESULTx + x
 
 

А можно создать в bat-файле функцию?

Да, можно. Более того, иногда даже нужно. Правда, функциями это можно назвать условно. Есть особый синтаксис команды call, который позволяет перейти на метку в этом же bat-файле с запоминанием места, откуда был произведен этот вызов:

 :метка аргументы

Возврат из функции производится командой:

Ключ /b здесь очень важен: без него будет произведен выход не из функции, а из сценария вообще. За подробностями обращайтесь к:


Что интересно, команда call с таким синтаксисом поддерживает рекурсивные вызовы с автоматическим созданием нового фрейма для переменных аргументов %0-%9. Иногда это может быть полезным. Вот классический пример рекурсивного подсчета факториала на командном языке:

@ 
 
exit
 
rem Функция для подсчета значения факториала
 %1 Число, для которого необходимо подсчитать факториал
%RESULT% Значение факториала
 (
exit /b
)
 (
exit /b
)
 /a PARAM - 
 
 /a RESULT *
exit /b
> factorial.bat 10
3628800

Как можно избежать использования goto?

На самом деле можно. Как правило, большинство меток и переходов используются для организации ветвлений при проверке условий, т.е. банальных if-then-else блоков. В оригинале, bat-язык поддерживал только одну команду в блоке then, что автоматически приводило к идиомам вида:

 condition 
rem Команды ветки ‘else’
 
rem Команды ветки ‘then’

Но к счастью, командный интерпретатор cmd.exe современных ОС Windows 2000 и старше поддерживает блоки команд в конструкциях ветвления, что устраняет необходимость применения меток. Блоки команд заключаются в круглые скобки. Выглядит это так (имитируя C/C++ indentation style):

 condition (
rem Команды ветки ‘then’
) (
rem Команды ветки ‘else’
)

Конкретный пример использования:

@ 
 
 (
 FAIL: Аргумент является обязательным ^(--debug, --release^)
exit /b
)
rem Удаляем из аргумента все дефисы для упрощения обработки
 -%
 (
 INFO: Устанавливаем debug-режим окружения
 /Od /MDd /Z7
) (
 INFO: Устанавливаем release-режим окружения
 /O2 /MD
)

На мой взгляд, с этим уже вполне можно жить. Но, как всегда, жизнь не так проста, как кажется. Есть одна проблема. Переменные, использующиеся в блоках then и else, раскрываются началом выполнения этих блоков, а не в процессе выполнения. В приведенном примере это не вызывает никаких проблем, однако в следующем вызовет:

 (
 INFO: Устанавливаем debug-режим окружения /Od
 /MDd /Z7
) (
 INFO: Устанавливаем release-режим окружения /O2
 /MD
)

Загвоздка в том, что в обоих блоках подстановка переменной OPTFLAGS произойдет до того, как она будет изменена в процессе выполнения этого блока. Соответственно, в CCFLAGS будет подставлено то значение, которое OPTFLAGS имела на момент начала выполнения данного if-блока.

в тексте самого bat-файла. Второй способ мне представляется более удобным – не очень здорово требовать от кого-то запуска твоего сценария с определенным параметром.

С учетом сказанного предыдущий «неправильный» пример может быть исправлен так:

 (
 INFO: Setting up debug mode environment /Od
 !OPTFLAGS! /MDd /Z7
) (
 INFO: Setting up release mode environment /O2
 !OPTFLAGS! /MD
)

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

Как обработать текстовый файл?

Иногда в командном файле необходимо получить доступ к содержимому некоторого текстового файла и некоторым образом это содержимое обработать. Например, прочитать файл настроек программы.

Для привнесения еще большей конкретики в процесс изучения зададимся целью прочитать файл с настройками следующего содержания:



Ничего сверхъестественного – простой key=value формат с возможностью вставки Unix-style комментариев. Помочь в чтении и обработке этого файла нам сможет команда for. Ее дополнительные опции позволяют задать и разделители, и символ начала комментария, и кое-что еще. Вот командный файл, который выполняет поставленную задачу:

@ 
rem Читаем настройки из файла settings.txt, который должен располагаться в
rem том же каталоге, что и bat-файл. Если не удалось распарсить настройки -
rem выходим с ненулевым кодом возврата.
 \settings.txt || exit /b 
rem Прочитанные настройки:
 Build mode : 
 Compiler : 
 Architecture: 
 
rem Выход из сценария. Дальше - только функции.exit /b 
 
rem Функция для чтения настроек из файла.
 %1 - Имя файла с настройками
 
rem Проверка существования файла
 not (
 FAIL: Файл с настройками отсутствует
exit /b
)
 
rem Обработка файла c настройками
eol=# указывает на то, что содержимое строки начиная с символа #
 delims== указывает, что разделителем значений является символ =
rem tokens=1,2 приводит к тому, что в переменную %%i будет занесен первый
rem токен, а в %%j - второй.
 /f "eol=# delims== tokens=1,2" in () (
 rem В переменной i - ключ
 rem В переменной j - значение
 rem Мы транслируем это в переменные окружения
)
exit /b 

Кстати, возможности команды for не ограничиваются чтением из файла. Возможно также чтение вывода другой команды. Например, так:

@ /f in (`cmd.exe /c ver`) (
) 

Особенно меня умиляет наличие опции “usebackq”, которая делает синтаксис отдаленно похожим на юниксовый. И в стенах царства Билла есть граждане, скучающие по /bin/sh и пытающиеся хоть как-то скрасить существование свое и окружающих. Следующий совет это также косвенно подтверждает.

Что это за упомянутые ранее операторы объединения команд?

Форма этих операторов весьма соответствует их содержанию. В случае, пожалуй, наименее полезного оператора & вторая команда будет просто выполнена после первой, т.е. это равносильно простой записи:

Оператор && гарантирует, что вторая команда будет выполнена только, если первая была выполнена успешно, т.е. с нулевым кодом возврата (он же %errorlevel%). Такие конструкции очень популярны в мире shell-сценариев Unix. Например:

 sources && make clean

Если перейти в каталог sources не удастся, то будет произведен выход с кодом ошибки 1. Если же первая команда отработает нормально, то вторая выполнена не будет. Например, такая простейшая защита помогла бы в случае с cd по UNC-адресу, описанному ранее.

Можно ли написать на bat-языке серьезную программу?

Пожалуй, нет. Серьезная программа должна все-таки выглядеть серьезно. А все написанное на командном языке Windows таковым назвать можно лишь с о-о-о-чень большой натяжкой. Так что для решения более сложных задач автоматизации лучше все-таки взять что-нибудь более функциональное:

  • Perl
  • Python
  • Ruby
  • JScript / VBScript

Последние, кстати, присутствуют в Windows 2000/XP по умолчанию (с некоторыми функциональными различиями) и в целом могут считаться заменой *.bat языку. Однако сдается мне, что *.bat-файлы проживут еще очень долго.

Как проверить, указан ли определенный аргумент в bat-файле?

@ 
 
 [][]
@ Это не выполнится, если параметр указан
@ Done. 
 
@ Usage: ^<EnvironmentName^>
exit /B 

Как можно отменить (экранировать) действие специальных символов (< и >)?

Это можно сделать с помощью символа ^ (см. предыдущий пример).

1Применение команды for в bat-файлах (technet.microsoft).
2. DOS Command Index site:earthlink.net.
3. О вреде оператора goto site:vspu.ac.ru.

Создание и чтение текстовых файлов в командной строкеЕсли вы оказались без доступа к чему-либо кроме командной строки или Windows PowerShell и по какой-то причине вам требуется возможность создания или чтения текстовых файлов, это вполне реализуемо, причем более чем одним методом.

:/>  Как перезагрузить ПК с Windows 10 через командную строку • Блог системного администратора

В этой инструкции подробно о работе с текстовыми файлами в командной строки или PowerShell (разумеется, можно и в Терминале Windows) — создание и сохранение текстовых файлов, их вывод и чтение в консоли.

Создание текстовых файлов в командной строке

Возможность создания текстовых файлов доступна как в командной строке (cmd.exe), так и в PowerShell. Начнем с первого варианта.

Во всех случаях учитывайте, что при использовании кириллицы потенциально возможны проблемы с кодировкой, а в некоторых случаях кодировка может отличаться при использовании разных команд.

Команда ECHO

echo Содержимое текстового файла > file.txt

В результате её выполнения в текущей рабочей папке командной строки будет создан файл с именем file.txt и содержимым «Содержимое текстового файла».

Создание текстового файла с помощью команды echo

COPY CON

Команда copy с параметром con позволяет скопировать содержимое консоли в файл. Использование возможности будет состоять из следующих шагов:

  1. Введите команду
    copy con имя_файла.txt

    файл не будет создан, но после выполнения указанной команды у вас появится возможность набрать содержимое этого файла, которое по завершении процесса будет в него сохранено.

  2. Курсор переместится на строчку ниже, и вы сможете набирать текст так, как делаете это обычно, включая перенос строки. Создание текстового файла с помощью copy con
  3. Для завершения набора и сохранения текстового файла нажмите сочетание клавиш Ctrl+Z, а затем — Enter. Это добавит отметку конца файла и сохранит его в текущей папке с указанным на 1-м шаге именем. Сохранение текстового файла с помощью copy con

Создание текстового файла в PowerShell

PowerShell также имеет набор встроенных командлетов для сохранения текстовых данных в файл.

Out-File

Использование Out-File в PowerShell по своей функциональности сходно с оператором перенаправления вывода в командной строке. Вывод консоли перенаправляется в заданный файл.

"Текстовая строка" | Out-File -FilePath .\file.txt

В этом примере в текущей папке PowerShell будет создан файл с именем file.txt и содержимым «Текстовая строка».

New-Item

Создание нового текстового файла в PowerShell возможно с помощью командлета New-Item. Пример команды, в которой создается текстовый файл file.txt, содержащий «Текстовая строка» в текущем расположении:

New-Item -Path . -Name "file.txt" -ItemType "file" -Value "Текстовая строка"

Создание текстового файла с помощью New-Item в PowerShell

Set-Content и Add-Content

Ещё два командлета PowerShell для работы с текстовыми файлами:

  • Set-Content — перезаписывает содержимое файла
  • Add-Content — добавляет содержимое в конце выбранного файла

Их использование можно увидеть на примере следующей команды:

Add-Content -Path .\file.txt -Value "Ещё одна текстовая строка"

Добавление текста к файлу в PowerShell

Вывод (чтение) текстового файла в командной строке и PowerShell

Теперь перейдем к способам просмотреть текстовые файлы в командной строке или PowerShell. Как и в предыдущем случае, учитывайте, что для файлов, содержащих кириллицу, возможны проблемы с отображением символов в правильной кодировке.

TYPE

Самый простой вариант — использование команды TYPE с указанием пути к файлу, который нужно отобразить в консоли, например:

type file.txt

Вывод текстового файла с помощью команды type

MORE

Если файл объемный и содержит большое количество строк, используйте команду more, например:

more file.txt

Выполнив команду, вы увидите часть содержимого текста, которая помещается в окне консоли, далее вы можете использовать следующие клавиши:

Вывод текстового файла с помощью команды more

  • Enter — для отображения следующей строки файла.
  • Пробел — для отображения следующих строк документа, которые поместятся в активное окно консоли.
  • P — Показать следующие N строк. После нажатия этой клавиши с последующим указанием количества строк, будет выведено соответствующее количество строк текстового документа.
  • S — пропустить следующие N строк, работает аналогично предыдущему варианту.
  • Клавиша «=» — для отображения текущего номера строки.
  • Q — для прекращения выполнения команды more.

Get-Content

Вывести содержимое текстового файла в PowerShell можно с помощью Get-Content с указанием пути к файлу, например:

Get-Content file.txt

Чтение текстового файла с помощью Get-Content в PowerShell

Также вы можете выводить определенные строки файла, с помощью команд вида (вывод первых или последних 10 строк соответственно):

Get-Content file.txt | Select-Object -First 10
Get-Content file.txt | Select-Object -Last 10

Или присвоить содержимое файла переменной и вывести конкретную строку:

$file_text = Get-Content file.txt
$file_text[2]

Текстовый редактор edit.com в Windows

Помимо использования ручного ввода команд, вы можете использовать консольные текстовые редакторы — сторонние в версиях для Windows, такие как Vim, Nano, Kinesics Text Editor или даже старый встроенный edit.com (может отсутствовать в вашей версии системы и требовать патча NTVDMx64).

Время на прочтение

Разделы можно пропускать без ущерба для понимания, ровно как и любые непонятные/неинтересные места в них.

Перенаправления

echo foo > bar
echo foo 2> bar
echo foo > bar 2>&1

Cat

Да, в Windows есть аналог многоликой команды cat, которая является одной из команд, выражающих суть UNIX’а. Это команда type. Она принимает один или несколько аргументов — имена файлов.

type file

Если нужно, чтоб type читал с экрана (например, если нужно создать файл, на лету наполнив его содержимым), то нужно набрать

type con > file

con — это аналог /dev/tty (подробнее об этом в следующем разделе).
То есть вышеприведённая команда является аналогом UNIX’овой команды cat /dev/tty > file или cat - > file или просто cat > file.

Когда вы закончите набирать файл, нажмите на новой строке Ctrl-Z и Enter. Это признак конца файла, аналог Ctrl-D в UNIX’е.

В Windows то же самое, Ctrl-Z и Enter заставляют getchar вернуть EOF.

/dev/null, /dev/tty и т.

Аналог /dev/null — это устройство nul. Причём оно как бы присутствует в каждой папке. Это тянется со времён старых версий DOS’а, когда не было папок.

Теперь о других устройствах. Аналог /dev/tty — это con, от слова console. Причём con — это аналог именно /dev/tty, а не /dev/console, так как в Windows у каждого окна командной строки con свой.

Аналоги /dev/ttyS0, /dev/ttyS1, /dev/ttyS2, /dev/ttyS3 — это com1, com2, com3, com4 (но винде есть ещё com5 и т. д.). Это устройства serial console, они же COM-порты, они же последовательные порты.

Обычными средствами винды нельзя создать файл или папку с именем con или nul и т. д. Но можно исхитриться: mkdir \\.\c:\con.

Есть шуточная версия того, почему в Windows трудно создать файл с именем con. А именно: у Билла Гейтса было прозвище con, то есть ботаник. Подробнее см., например, здесь: vk.com/wall-31439745_2474 (естественно, этой информации нельзя доверять).

Подробнее про эти устройства тут: en.wikipedia.org/wiki/Device_file#MS-DOS.

/dev, /dev/sda1,.

После прочтения предыдущего раздела у вас мог возникнуть вопрос: и что, всё? /dev/null, /dev/tty и ещё несколько штук девайсов? А где /dev/sda1 и прочие бесчисленные устройства? Ведь в GNU/Linux’е папка /dev может содержать сотни устройств!

Ответ таков: да, в Windows есть целая папка с такими устройствами. Это \Device. Её сложно посмотреть через обычный пользовательский интерфейс. Там лежат устройства типа \Device\HarddiskVolume1 — это аналог GNU/Linux’ового /dev/sda1.

Эти устройства появились в NT-шных версиях Windows’а и не тянутся с DOS’овых времён, в отличие от устройств из предыдущего раздела.

Пайпы, они же конвееры

cmd1 | cmd2, так же, как и в UNIX.

/etc/fstab

Его аналог — это ветка HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices в реестре Windows (да, да, в винде, как и в UNIX, есть понятие монтирования). Кстати, если у вас до этого были проблемы с переносом установленного Windows’а с одного раздела на другой, или с переименованием дисков в Windows’е или с чем-то ещё подобным, то — вот оно, решение!

Если, скажем, вы перенесли Windows с одного раздела на другой, то после этого нужно сделать два шага: разобраться с загрузчиком и его конфигами (об этом в следующем разделе) и подредактировать этот самый ключ реестра (в общем-то так же, как и в GNU/Linux’е: GRUB + fstab). Если ключ не подредактировать, то винда загрузиться не сможет, так начнёт грузиться с нового раздела (то есть того, на который мы копирнули винду), а продолжит — со старого (то есть того, с которого мы копирнули винду). Все системные вещи будут загружены с нового, а всякие Касперские — со старого. Итак, нужно удалить из этой ветки все записи, кроме записи “(По умолчанию)”. Тогда винда забудет всё, что знала о разделах и при следующем запуске будет считать своим разделом тот, с которого запустилась (что нам и надо). Короче говоря, автоматически определит разделы.

Ещё несколько вариантов:

  • Почистить реестр, выключить компьютер (можно «жёстко»), а потом копирнуть винду. Однако, я это не проверял. Не факт, что винда даст вам отредактировать этот ключ реестра и что она не заполнит его снова при выключении
  • Отредактировать реестр, и сразу же, не выключая комп, копирнуть запущенную винду на другой раздел. Но и это тоже не проверялось
  • Если вы копируете винду с одного физического диска на другой, можно после копирования вынуть из компьютера старый физический диск и загрузиться в новый хотя бы один раз (чтоб винда обновила MountedDevices). Потом можно вставить старый диск обратно. Такой же трюк можно проделать даже с разделами на одном физическом диске: просто временно удалить старый раздел, а потом восстановить его обратно (ясно, что делать это нужно крайне осторожно). Ну и конечно же, всё это не проверялось :))
  • Смонтировать реестр Windows в GNU/Linux как winregfs

И наконец: использовать разные программы для копирования/бекапов разделов (типа Acronis) бесполезно: все они не меняют реестр (скорее всего), поэтому работать в такой ситуации (копирование винды в пределах одного компа) не будут.

И ещё: весь материал этого раздела проверялся только на Windows XP.

/boot/grub/grub. cfg

В Windows XP его аналог — это файл boot.ini в корне раздела с Windows, а в Windows 7 — это Windows Boot Manager.

Мощный командный интерпретатор

После лицезрения этой таблицы все юниксоиды, конечно же, схватились за голову и сказали: «Что за идиоты проектировали винду?» Впрочем, в UNIX’е тоже не всё гладко: с какой стати set -x включает дебаг, а set +x выключает его??? То же самое относится к остальным режимам, включаемым командой set.

Ах да, я же обещал мощный командный интерпретатор. 🙂 cmd.exe таковым, конечно же, не является. А вот PowerShell — является. Одной из особенностей PowerShell’а является то, что он «понимает» обычные UNIX’овые команды, например, ls. Правда, на самом деле эта команда похожа на UNIX’овую лишь своим названием и идеей, опции у этого ls всё равно совсем другие. ls — это всего лишь один из алиасов на Get-ChildItem. А ещё в винде есть полноценный IDE для написания PowerShell-скриптов с визуальным отладчиком! Вы можете себе такое представить в UNIX’е? Да, есть конечно bashdb, но визуальный отладчик, конечно же, удобнее.