I've got a task to change encoding of .txt file to Windows-1251, OEM866 and UTF-8 using only cmd recently. I've tried using:
chcp 866
cmd /u /c /d type 1.txt > 866.txt
But the text file had UTF-16 encoding, despite looking like a OEM866 text.
I'd say that the task (convert encoding of given files from one encoding to another like iconv tool does) is solvable using only cmd: first, create two auxiliary binary files bomUtf16le.bin and bomUtf8.bin as follows:
REM do dot run as a batch file; copy&paste the code into an open cmd window
:: create a testing folder and change the current directory
2>NUL md .\SO\69595742
pushd .\SO\69595742
:: create file bomUtf16le.bin (BOM, encoding utf16LE)
>NUL chcp 1252
<nul set /p x=ÿþ>bomUtf16le.bin
:: create file bomUtf8.bin (BOM, encoding utf8)
>NUL chcp 1252
<nul set /p x=>bomUtf8.bin
:: create file a1200.txt (a Cyrillic text, encoding utf16LEbom)
>NUL copy /Y /B bomUtf16le.bin a1200.txt
cmd /U /D /C "(echo русский текст&echo кирилловский шрифт)>>a1200.txt"
popd
Important: do dot run above code snippet from a batch file; copy&paste the code into an open cmd window! The code creates an initial testing file a1200.txt (encoding utf16LEbom). We could begin with a file of any supported encoding 1251 or 866 or 65001(==Utf8bom) because below conversions are designed to work cyclically (proved by binary comparison using fc command, and manually confirmed by opening all files in notepad++). The following code snippet assumes initial testing file encoding utf16LEbom.
Then run the following (run as a batch file, or copy&paste the code into an open cmd window):
#ECHO OFF
SETLOCAL EnableExtensions
:: run as a batch file, or copy&paste the code into an open cmd window
2>NUL md .\SO\69595742
pushd .\SO\69595742
:: convert file a1200.txt to cp1251
>NUL chcp 1251
type a1200.txt>x1251.txt
:: convert file a1200.txt to cp866
>NUL chcp 866
type a1200.txt>x866.txt
:: convert file a1200.txt to utf-8 BOM
>NUL copy /Y /B bomUtf8.bin x65001bom.txt
>NUL chcp 65001
type a1200.txt>>x65001Bom.txt
:: convert file x866.txt to file x1200.txt (encoding utf16LEbom)
>NUL copy /Y /B bomUtf16le.bin x1200.txt
>NUL chcp 866
cmd /U /D /C "type x866.txt>>x1200.txt"
:: Perform a binary comparison (FC: no differences encountered)
fc /B x1200.txt a1200.txt
:: convert file x1251.txt to file y1200.txt (encoding utf16LEbom)
:: analogous to: x866.txt to file x1200.txt
>NUL copy /Y /B bomUtf16le.bin y1200.txt
>NUL chcp 1251
cmd /U /D /C "type x1251.txt>>y1200.txt"
:: Perform a binary comparison (FC: no differences encountered)
fc /B y1200.txt a1200.txt
:: convert file x65001bom.txt to file z1200.txt (encoding utf16LEbom)
>NUL chcp 65001
cmd /U /D /C "type x65001bom.txt>z1200.txt"
:: Perform a binary comparison (FC: no differences encountered)
fc /B z1200.txt a1200.txt
:: convert file a1200.txt to x65001noBom.txt (utf-8 no BOM, merely for completeness)
>NUL chcp 65001
type a1200.txt>x65001noBom.txt
dir *.txt | findstr /I "\.txt$"
popd
goto :eof
Result: .\SO\69595742.bat
Comparing files x1200.txt and A1200.TXT
FC: no differences encountered
Comparing files y1200.txt and A1200.TXT
FC: no differences encountered
Comparing files z1200.txt and A1200.TXT
FC: no differences encountered
17/10/2021 19:24 72 a1200.txt
17/10/2021 21:49 72 x1200.txt
17/10/2021 21:49 35 x1251.txt
17/10/2021 21:49 67 x65001Bom.txt
17/10/2021 21:49 64 x65001noBom.txt
17/10/2021 21:49 35 x866.txt
17/10/2021 21:49 72 y1200.txt
17/10/2021 21:49 72 z1200.txt
Summary (incomplete): file conversions (⇆ reversible)
Direct:
utf-16-le-bom ⇆ cp866
utf-16-le-bom ⇆ cp1251
utf-16-le-bom ⇆ utf-8-bom
utf-16-le-bom → utf-8-noBom
Possible (thru an auxiliary file):
cp866 ⇆ utf-16-le-bom ⇆ cp1251
cp866 ⇆ utf-16-le-bom ⇆ utf-8-bom
utf-8-bom ⇆ utf-16-le-bom ⇆ cp1251
Possible utf-8-noBom → utf-8-bom as follows:
copy /B bomUtf8.bin + fileutf-8-noBom.txt fileutf-8-bom.txt
Tested in Windows 10 with the following Administrative language settings; not tested with that Beta checkbox unticked:
If you wish to stick to cmd then you may need the old 2004 iconv transcoder tools so here is a download.cmd to get iconv.exe conversion and the support files. however read Force encode from US-ASCII to UTF-8 (iconv) for any relevant advice as its easy to use the wrong input to transcode from.
#echo off & Title Get-iConv
Rem Download libiconv-1.9.1 and support files on Windows 10 optionally include gettext-tools
set "iconv-dir=c:\text-iconv"
if not exist "%iconv-dir%" md "%iconv-dir%"
cd /d "%iconv-dir%"
if not exist gt-runtime.woe32.zip curl -o gt-runtime.woe32.zip http://ftp.gnu.org/gnu/gettext/gettext-runtime-0.13.1.bin.woe32.zip
tar -xf gt-runtime.woe32.zip bin
tar -xf gt-runtime.woe32.zip share/doc
Rem if not exist gt-tools.woe32.zip curl -o gt-tools.woe32.zip http://ftp.gnu.org/gnu/gettext/gettext-tools-0.13.1.bin.woe32.zip
Rem tar -xf gt-tools.woe32.zip bin
Rem tar -xf gt-tools.woe32.zip share/doc
if not exist libiconv.woe32.zip curl -o libiconv.woe32.zip http://ftp.gnu.org/gnu/libiconv/libiconv-1.9.1.bin.woe32.zip
tar -xf libiconv.woe32.zip bin
tar -xf libiconv.woe32.zip share/doc
cd bin
start "" cmd /k "%iconv-dir%\bin\iconv.exe" -h
start "" "%iconv-dir%\share\doc\libiconv\iconv.1.html"
start "" https://stackoverflow.com/questions/11303405/force-encode-from-us-ascii-to-utf-8-iconv
Related
I write code to backup file to Map disk. It worked when I run it manual (created zip file and copy file to map disk).
Here is my code:
#echo off
set CUR_YYYY=%date:~10,4%
set CUR_MM=%date:~4,2%
set CUR_DD=%date:~7,2%
set CUR_HH=%time:~0,2%
if %CUR_HH% lss 10 (set CUR_HH=0%time:~1,1%)
set CUR_NN=%time:~3,2%
set CUR_SS=%time:~6,2%
set CUR_MS=%time:~9,2%
set SUBFILENAME=web2_%CUR_YYYY%%CUR_MM%%CUR_DD%-%CUR_HH%%CUR_NN%%CUR_SS%
md C:\Backup\"%SUBFILENAME%"
md C:\Backup\"%SUBFILENAME%"\05_SOHOA_HOSOLUUTRU
XCOPY "E:\Data_SoHoa\05_SOHOA_HOSOLUUTRU" "C:\Backup\%SUBFILENAME%\05_SOHOA_HOSOLUUTRU" /E
md C:\Backup\"%SUBFILENAME%"\05_SOHOA_HOSOLUUTRU_API
XCOPY "E:\Data_SoHoa\05_SOHOA_HOSOLUUTRU_API" "C:\Backup\%SUBFILENAME%\05_SOHOA_HOSOLUUTRU_API" /E
md C:\Backup\"%SUBFILENAME%"\DATA
XCOPY "E:\Data_SoHoa\DATA" "C:\Backup\%SUBFILENAME%\DATA" /E
XCOPY "E:\Data_SoHoa\setup-TcpServerService.exe" "C:\Backup\%SUBFILENAME%\" /X
set PATH=C:\Program Files\7-Zip\
SETX MYPATH "%PATH%"
7z a C:\"%SUBFILENAME%".zip C:\Backup\"%SUBFILENAME%"
set copyfile = C:\%SUBFILENAME%.zip
COPY "C:\%SUBFILENAME%.zip" "Z:\Backup\TLAM_sohoa\%SUBFILENAME%.zip"
Then I setup Task Scheduler to auto run this bat script. It created zip file, but not copy this zip file to map disk and return (0x1) result.
Here is my setup
I have decided to post this as a rewritten example. It formulates the date string in a none locale/PC dependent manner, reduces repetetive and unnecessary commands, replaces the deprecated XCopy with RoboCopy and uses PushD to create a temporary mapping to your server location for the final copy command.
#Echo Off
Set "SubFileName="
For /F "Tokens=1-6Delims=/: " %%A In ('RoboCopy/NJH /L "\|" Null'
)Do If Not Defined SubFileName Set "SubFileName=web2_%%A%%B%%C-%%D%%E%%F"
Set "CopyFile=C:\%SubFileName%.zip"
For %%A In ("05_SOHOA_HOSOLUUTRU" "05_SOHOA_HOSOLUUTRU_API" "DATA"
)Do RoboCopy "E:\Data_SoHoa\%%~A" "C:\Backup\%SubFileName%\%%~A" /E
RoboCopy "E:\Data_SoHoa" "C:\Backup\%SubFileName%" "setup-TcpServerService.exe" /CopyAll
"%ProgramFiles%\7-Zip\7z.exe" a "%CopyFile%" "C:\Backup\%SubFileName%"
PushD "\\server…\Backup\TLAM_sohoa"
Copy "%CopyFile%"
PopD
Just modify server… on line 10 to the UNC path of the location, which after logon would be, associated with Z:
Hopefully this is a quick and easy question...
I have the same issue as this user: https://superuser.com/questions/812455/recursively-fixing-image-file-extensions-in-linux except I'm using a Windows (7) machine. (Most software ignores the extension like BlamKiwi mentions, but I'm frequently running into issues with Adobe software.)
I'm asking SO instead of SU since I just need some help translating the 'best answer' code into something that works on my machine.
for f in *.{jpg,JPG,png,PNG,jpeg,JPEG}; do
type=$( file "$f" | grep -oP '\w+(?= image data)' )
case $type in
PNG) newext=png ;;
JPEG) newext=jpg ;;
*) echo "??? what is this: $f"; continue ;;
esac
ext=${f##*.} # remove everything up to and including the last dot
if [[ $ext != $newext ]]; then
# remove "echo" if you're satisfied it's working
echo mv "$f" "${f%.*}.$newext"
fi
done
I'm guessing a .batch file can accomplish this but don't know enough to write it myself.
IrfanView is a freeware (for private usage) multimedia viewer which displays on viewing image files by default a message box if an image file has a file extension not suitable for image format prompting the user to rename the file for correcting the file extension. This message prompt can be disabled in configuration, but it is really useful to detect image files with wrong file extension on viewing them.
Images in Portable Network Graphics format always start with the 4 bytes 89 50 4E 47 (hexadecimal) which are displayed in a command prompt window on using code page 437 (North America) or code page 850 (Western Europe) as ëPNG.
Images in JPEG File Interchange Format start with the 10 bytes FF D8 FF E0 s1 s2 4A 46 49 46. The last 4 bytes of those 10 bytes are JFIF. s1 s2 are variable as being a length information.
The command FINDSTR is designed for searching for strings in text files, but can be used also for searching for strings in binary files. This is used by the batch file below:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "MessageOutput="
for /F "delims=" %%I in ('dir *.jpg *jpeg *.png /A-D /B /ON 2^>nul') do (
%SystemRoot%\System32\findstr.exe /M /C:PNG "%%I" >nul
if errorlevel 1 ( set "IsPNG=" ) else set "IsPNG=1"
%SystemRoot%\System32\findstr.exe /M /C:JFIF "%%I" >nul
if errorlevel 1 ( set "IsJPG=" ) else set "IsJPG=1"
if defined IsPNG if defined IsJPG (
set "FirstPNG=1"
for /F "delims=:" %%J in ('%SystemRoot%\System32\findstr.exe /N /C:PNG "%%I"') do (
if defined FirstPNG (
if "%%J" == "1" ( set "IsJPG=" ) else set "IsPNG="
set "FirstPNG="
)
)
)
if defined IsPNG (
if /I not "%%~xI" == ".png" (
echo PNG image "%%I" has wrong file extension.
ren "%%I" "%%~nI.png"
set "MessageOutput=1"
)
) else if defined IsJPG (
if /I "%%~xI" == ".png" (
echo JPG image "%%I" has wrong file extension.
ren "%%I" "%%~nI.jpg"
set "MessageOutput=1"
)
) else (
echo/
echo ERROR: File "%%I" is neither a JPG nor a PNG file.
echo/
set "MessageOutput=1"
)
)
if defined MessageOutput (
echo/
pause
)
endlocal
The command DIR is executed by command FOR in a separate command process in background to get a list of *.jpg, *.jpeg and *.png file names without path of files in current directory on execution of the batch file.
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
It is necessary here to use command DIR instead of using
for %%I in (*.jpg *jpeg *.png) do (
because the list output by DIR, captured and processed by FOR line by line does not change anymore during the loop iterations. This is important here because of perhaps changing the list of file entries in current directory due to a rename operation. By using FOR directly it could happen after a file rename that a file is processed twice or another file in directory is skipped because of directory list change during loop iteration.
The code is written to avoid usage of delayed environment variable expansion to work also for files with an exclamation mark. A different solution would be also possible with using a subroutine.
For each file found by DIR first a case-sensitive search for PNG is executed on the file and environment variable IsPNG is deleted on not found in file or is defined with value 1 on file containing PNG.
Next a case-sensitive search for JFIF is executed on the file and environment variable IsJPG is deleted on not found in file or is defined with value 1 on file containing JFIF.
Binary data of an image file can contain anywhere in the data by chance also the hexadecimal byte sequence 50 4E 47 or 4A 46 49 46. The third IF command line checks if the file contains both byte sequences. In this rare case FINDSTR searching for PNG is executed once again with evaluating in which "line" the string is found. If the line number is 1, then the string PNG is definitely at top of the file which is a quite clear indication that the file is a PNG file, otherwise it should be a JPEG file containing by chance also the bytes 50 4E 47. The worst case handled by the batch code is a PNG image file containing PNG in header and in data PNG and JFIF which requires evaluating only first occurrence of PNG found by FINDSTR.
An appropriate message is output and file is renamed (without checking for success) if current image file is (most likely) a PNG file, but does not have expected file extension .png. For a *.png file being (most likely) a JPEG file a similar message is output and the file rename is executed for changing the file extension.
It is also possible that the file with extension .png, .jpg or .jpeg does neither contain PNG nor JFIF, for example on being a GIF file. In this case an error message is output as the image format could not be determined by this batch code.
The batch file execution is halted at end in case of any message is output. This means on double clicking the batch file a console window appears and closes if all *.jpg, *.jpeg and *.png file have the right file extension according to image format.
Of course this solution is definitely not perfect. A text file with first line containing PNG and second line containing JFIF and having the file extension .jpg would interpreted as PNG image file although being in real a text file. IrfanView is definitely a better choice for really checking if a *.jpg, *.jpeg or *.png file is really a JPEG or PNG image file.
Here is additionally an alternate solution using a subroutine:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "MessageOutput="
for /F "delims=" %%I in ('dir *.jpg *jpeg *.png /A-D /B /ON 2^>nul') do call :CheckImage "%%I"
if defined MessageOutput (
echo/
pause
)
endlocal
goto :EOF
:CheckImage
set "IsJPG=0"
set "IsPNG=0"
%SystemRoot%\System32\findstr.exe /M /C:PNG %1 >nul
if not errorlevel 1 set "IsPNG=1"
%SystemRoot%\System32\findstr.exe /M /C:JFIF %1 >nul
if not errorlevel 1 set "IsJPG=1"
if %IsPNG% == 1 if %IsJPG% == 1 (
for /F "delims=:" %%J in ('%SystemRoot%\System32\findstr.exe /N /C:PNG %1') do (
if "%%J" == "1" ( set "IsJPG=0" ) else set "IsPNG=0"
goto CheckExtension
)
)
:CheckExtension
if %IsPNG% == 1 (
if /I not "%~x1" == ".png" (
echo PNG image %1 has wrong file extension.
ren %1 "%~n1.png"
set "MessageOutput=1"
)
goto :EOF
)
if %IsJPG% == 1 (
if /I "%~x1" == ".png" (
echo JPG image %1 has wrong file extension.
ren %1 "%~n1.jpg"
set "MessageOutput=1"
)
goto :EOF
)
echo/
echo ERROR: File %1 is neither a JPG nor a PNG file.
echo/
set "MessageOutput=1"
goto :EOF
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
endlocal /?
findstr /?
for /?
if /?
pause /?
ren /?
set /?
setlocal /?
I have some batch files that use a text file for language-independancy. Until yesterday all worked fine ... but then I began translating the standard texts to Dutch and German. Both languages use so called diacritical or accented characters like ä, ë, ö. I think Spanish will give the same problems with ñ. I created the text file with Notepad using standard encoding, which is ANSI. Just typing (DOS: TYPE) the file showed the wrong accented characters: e.g. ë showed as Ù. After I edited the text file and saved with Unicode encoding the DOS TYPE showed exactly what I typed in Notepad. At this point I thought my problem was solved ... but my batch code now shows me no text at all! All text is retrieved from the file by a batch file that looks like this (simplified):
#rem Parms %1 text type number File %%a program name
#rem %2 program name (double quoted) %%b - - filler (tabs)
#rem %3 text number %%c text number
#rem %4 replacement value - 1 %%d - - filler (tabs)
#rem %5 replacement value - 2 %%e text string
set TempText=
set TempType=
setlocal enabledelayedexpansion
#rem Read file until both values are set ...
for /f "usebackq tokens=1,2,3,4,5 delims=|" %%a in ("%EnvPath%Text.txt") do (
if /i %%a==Tools (if /i %%c==%1 (set TempType=%%e))
if /i %%a==%~2 (if /i %%c==%3 (set TempText=%%e))
if not "!TempType!"=="" (if not "!TempText!"=="" (goto :Leave))
)
:Leave
endlocal & set TempText=%TempText%&set TempType=%TempType%
When ECHO is ON it shows that no lines are read from the file or the FOR-loop is never executed.
My question is: how can I make the FOR loop to read the Unicode texts?
Your problem is that cmd uses code page 850 (in the US it may be 437), type chcp to see. English Windows uses 1252 elsewhere.
GUI programs
ñ 0xf1
Console programs
ñ 0xa4
If you are on 32 bit use edit.exe (a msdos text editor). Else you can use Word and save as MSDos text.
three years late, but...
you can convert the file to ANSI "on the fly" with the type command:
... %%a in ('type "%EnvPath%Text.txt"') do (
I created a custom file extension I would associate to a batch script.
I used
ASSOC .myext=MY.FILETYPE
FTYPE MY.FILETYPE=cmd /c "C:\Path\of\my\batch.bat" %1 %*
by now the batch file "C:\Path\of\my\batch.bat" is a simple one-liner
echo %1
And roughly works: double clicking a .myext file pops up a cmd shell echoing the file path.
But a problem arises when the .myext file is in a path containing spaces: the echoed filepath is truncated to the space.
Double quoting the %1 in the FTYPE statement seems not to work.
FTYPE MY.FILETYPE=cmd /c "C:\Path\of\my\batch.bat" "%1" %*
Double quoting %1 is correct, but it fails as cmd.exe contains a bug when the command and at least one parameter contains quotes.
So you need to make the command without quotes by inserting CALL.
FTYPE MY.FILETYPE=cmd /c call "C:\Path\of\my\batch.bat" "%1" %*
Change the batch file "C:\Path\of\my\batch.bat" content to
echo %*
Your ASSOC and FTYPE statements seem to be all right.
Edit accordig to Monacraft's comment.
This solution is correct as %1 will reference the document filename while that %* will reference to further parameters: If any further parameters are required by the application they can be passed as %2, %3. To pass all parameters to an application use %*.
Handy for using aFile.myext a b c right from command line, although for that use the FTYPE statement should be
FTYPE MY.FILETYPE=cmd /D /C "C:\Path\of\my\batch.bat "%1"" %*
to differentiate first parameter if contains spaces.
Example: with
ASSOC .xxx=XXXFILE
rem a bug here FTYPE XXXFILE=%ComSpec% /D /C "d:\bat\xxxbatch.bat "%1"" %*
rem definitely switched to Jeb's solution as follows
FTYPE XXXFILE=%comspec% /D /C call "d:\bat\xxxbatch.bat" "%1" %*
and xxxbatch.bat as follows
#echo(
#echo %*
#if "%2"=="" pause
#goto :eof
Output:
d:\bat>D:\test\xxxFileNoSpaces.xxx aa bb cc
"D:\test\xxxFileNoSpaces.xxx" aa bb cc
d:\bat>"D:\test\xxx file with spaces.xxx" dd ee
"D:\test\xxx file with spaces.xxx" dd ee
d:\bat>
if you are using this from a bat file try to change it to:
ASSOC .myext=MY.FILETYPE
FTYPE MY.FILETYPE=cmd /c "C:\Path\of\my\batch.bat" "%%1" %%*
I think even
FTYPE MY.FILETYPE="C:\Path\of\my\batch.bat" "%%1" %%*
should work.
I'm trying to open a file in it's default editor after the user has created the file. So far my script is:
#echo off
#echo --- Create A New File ---
#echo -
#echo Where should we put the new file?
set /p fileLocation=# %UserProfile%\
#echo -
#echo What do you want to call your new file?
set /p fileName=#
#echo -
#echo Almost Done! What is the files extension?
set /p extension=# .
#echo -
copy NUL "%UserProfile%\%fileLocation%\%fileName%.%extension%"
(ignore the extra echos and '#' those are just for fun)
After I click the file, it does the command: Choose Location > Choose File Name > Choose File extension. I'm almost done on what I want but theres one last thing. How can I get the file name that I created and then open in its default text-editor?
You can use start to open the file with the associated application.
Resources :
Open a File in the Default Application using the Windows Command Line (without JDIC) (waybackmachine capture from Oct 30, 2010)
In windows you can use start (http://ss64.com/nt/start.html).
start "" "%UserProfile%\%fileLocation%\%fileName%.%extension%"
You can also use explorer.exe/explorer to open the file (e.g. explorer file.txt). This also works nicely if you use WSL, especially with an alias like alias open="explorer.exe" so you can just call it like, e.g., open file.txt.
I achieved the correct way of FILE ASSOCIATION using these cmd commands.
this is just an example:
REG ADD "HKEY_CLASSES_ROOT\Applications\notepad++.exe\shell\open\command" /v # /t REG_SZ /d "\"C:\\Program Files\\Noteepad++\\notepad++.exe\" \"%1\"" /f
REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt" /v "Application" /t REG_SZ /d "notepad++.exe" /f
REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\OpenWithList" /v "g" /t REG_SZ /d "notepad++.exe" /f
assoc .txt=MyCustomType
ftype MyCustomType="C:\Program Files\Noteepad++\notepad++.exe" "%1"
(it's better to put them in .bat file)