EDIT: My essential question (without the specific setting for which I need a solution, as described in my original posting):
BinFile.bin is a file concatenated from binary files and a text file. The included text file consists only of lines beginning with a specific string, e.g. ;;;===,,,
With a batch file:
findstr /v "^;;;===,,," "BinFile.bin" > output.bin
an output bin file is generated in which the text file is completely removed.
How to use findstr (or another dos command) to not only remove all lines beginning with the specified string, but also the part of the bin before first such line (i.e. the complete binary part preceeding the text file)?
>>> My original posting:
jeb invented a method to concatenate files using Windows native tools which can be unconcatenated (in a specific way) using native tools. His solution is just ingenious!
copy /a batchBin.bat + /b myBinaryFile.bin /b combined.bat
with batchBin.bat:
;;;===,,,#echo off
;;;===,,,echo line2
;;;===,,,findstr /v "^;;;===,,," "%~f0" > output.bin
;;;===,,,exit /b
"The key is the findstr command, it outputs all lines not beginning with ;;;===,,,.
And as each of them are standard batch delimiters, they can be prefix any command in a batch file in any combination."
So myBinaryFile.bin can be extracted from the combined.bat––only by means of native tools!
My question:
In jeb's example the combined file is a batch file, because the first file in the copy command is a batch file. Could jeb's tricky method be used for the following task too, where the combined file would be combined.exe, an exe file?
copy /b aBat2ExeFile.exe + /a delimiter.bat + /b myBinaryFile.bin /b combined.exe
where delimiter.bat would be something like this:
;;;===,,,REM
and aBat2ExeFile.exe would be a batch file (aBat2ExeFile.bat) converted to exe, with a tricky use of findstr like in batchBin.bat, but with the result
[...] > output.exe
In aBat2ExeFile.bat findstr should be used with the result that all lines of combined.exe before and including the line ';;;===,,,REM' would be ignored and output.exe would be equal to myBinaryFile.bin again?
In think the concept is correct. But how this could be implemented in the aBat2ExeFile.bat?
EDIT: My question can be simplified (the frame described above is not essential):
How the findstr method used by jeb could be adapted to process a binary file in such a way that not only lines starting with ';;;===,,,' but also all lines preceding the first such line are "ignored"?
Related
I want to take a folder with several (15 in this first case) 'subtitle.srt' files (which, as I'm sure you're aware, are just text files with the extension ".srt" instead of ".txt") and modify each file in turn so that a new subtitle is added at the start of each file.
I want the new subtitle to be:-
0
00:00:00,001 --> 00:00:02,100
"Filename"
So, for example, if the first subtitle file in the folder is called "01. What Lies Beneath.srt" and it looks like this:-
1
00:00:02,120 --> 00:00:03,560
<font color="#FFFF00">Previously on Superman & Lois...</font>
2
00:00:03,560 --> 00:00:06,880
<font color="#00FFFF">I'm stepping down from active duty.</font>
<font color="#00FF00">You're going to be hard to replace.</font>
3
Etc., etc...
then after processing, I want it to look like this:-
0
00:00:00,001 --> 00:00:02,100
01. What Lies Beneath
1
00:00:02,120 --> 00:00:03,560
<font color="#FFFF00">Previously on Superman & Lois...</font>
2
00:00:03,560 --> 00:00:06,880
<font color="#00FFFF">I'm stepping down from active duty.</font>
<font color="#00FF00">You're going to be hard to replace.</font>
3
Etc., etc...
I'm rubbish at batch coding so I tried searching out possible ways to do it but nothing I tried worked!
Below are some attempts I made using different "routines" I found; each successive attempt separated (from last to first) by the PAUSE, EXIT commands:-
for %%a in (*.txt) do type append_ns0 >> %%a.srt
pause
exit
for %%a in (*.txt) do type append_ns0 >> %%a
for %%a in (*.txt) do type "%%~na" >> %%a
for %%a in (*.txt) do type append_spc >> %%a.srt
pause
exit
for %%I in (*.txt) do copy "C:\Users\wbcam\Desktop\G classroom\AddTitle.txt"+"%%~nI"+" "+"%%I" "%%~nI.srt"
pause
exit
for %X in (C:\Users\wbcam\Desktop\G classroom\Add Titles\*.txt) do type C:\Users\wbcam\Desktop\G classroom\AddTitles.txt >> %X
pause
exit
To use the COPY command I had to first rename the files from .srt to .txt (I'd rather NOT have to do that; I'm hoping someone can show me how to work on the ,srt files without any intermediate stages) and COPY also seemed to add a hex1A character to the end of the new file but, of course, it couldn't handle the insertion of the Filename (a text string) into the new file as it would only concatenate files not strings (if I, eventually, understood it's operation correctly, Doh!).
And attempts to use the ECHO or TYPE commands just seemed to overwrite everything in the original file leaving only:-
0
00:00:00,001 --> 00:00:02,100
and bugger all else!
Can anyone help out, please?
#ECHO OFF
SETLOCAL
rem The following setting for the source directoryis a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
FOR /f "delims=" %%b IN (
'dir /b /a-d "%sourcedir%\*.srt" '
) DO (
(
ECHO 0
ECHO 00:00:00,001 --^> 00:00:02,100
ECHO "%%~nb"
ECHO.
TYPE "%sourcedir%\%%b"
)>"%sourcedir%\%%~nb.txt"
MOVE "%sourcedir%\%%~nb.txt" "%sourcedir%\%%b" >NUL
)
GOTO :EOF
Always verify against a test directory before applying to real data.
Perform a directory scan. assigning each filename that matches the mask to %%b.
Write the two required lines, a line containing the name part of the filename in quotes and an empty line to the output, then type the contents of the selected file. Note that the > character in the text needs to be escaped by a caret. The output of the echoes is gathered and redirected to a .txt file and the .txt file is then written over the original file. The 1 file(s) copied message is suppressed by the >nul.
If you prefer, you could replace the two echo lines that insert the fixed text with type somefilename where somefilename contains the fixed text required.
You could replace the move line for testing with
FC "%sourcedir%\%%~nb.txt" "%sourcedir%\%%b"
which will show the differences.
copy adds the control-z following an archaic convention that ^Z marked end-of-file for text files.
--- Addition in response to comment
for /? from the prompt generates documentation about the for command - in general, commandname /? generates documentation for any command, although some commands require -? or -h or --h or --help. Utility designers generally follow the same convention and the details depend on the platform for which the software was originally designed.
for /f ... ('command....') do ... interprets the command-output as though it was a file.
The dir command reports the filenames and subdirectorynames in a directory. By default, it produces a formatted report including filesize and last-update date, but has numerous options including /b to produces a "basic" report (names only, no sizes, headers, summary, dates ,etc.) and /a-d which suppresses directorynames. The /s option means 'and list subdirectories too'. It can also accept a filemask (or ambiguous filename) - which applies equally to directorynames. If the filename supplied contains a ? then this means any ONE character or * which means any number of any characters - any other characters are taken literally and will match regardless of case. Hence, *.srt means any number of any characters followed by .srtwhich should select all file/directorynames that end.srt. The filemask may be preceded by *directoryname\\* which means scan this directory- but *that* directoryname may **not** contain?or*`.
When for /f is supplied with a filename list in basic form, each filename in the list is assigned to the metavariable assigned (%%a in this example) in turn and the do statements are executed using the assigned value in the metavariable. Again, there are many ways of having for /f interpret the value-string that is assigned to the metavariable. Many, many examples of these on SO
In the days of CP/M, filesize was a number of 128-byte blocks. Since files were not often a multiple of 128 bytes long, convention was that a control-z marked the end-of-file. Backwards-compatibility is a big issue in computing as it's wasteful to revise existing systems to cater for a concept-revision. Hence, the control-Z convention is still recognised and observed for text files.
this is for my doctoral thesis in medicine. So please excuse my noobishnis in programing.
I have a bunch (about 4000 files) of scans from patients. There is a front and a back .jpg for each patient. And there where multiple patients each day.
The folder structure looks like this:
\images
\2017-08-21
\pa_102165.jpg
\pa_10216500001.jpg
\2017-06-14
\pa_101545.jpg
\pa_10154500001.jpg
\pa_104761.jpg
\pa_10476100001.jpg
\pa_107514.jpg
\pa_10751400001.jpg
\2017-03-73
\pa_109631.jpg
\pa_10963100001.jpg
\pa_108624.jpg
\pa_10862400001.jpg
Where in the first example 2017-08-21 is the date the patient came in, pa_102165.jpg is the front and pa_10216500001.jpg is the back. So the front is always pa_10XXXX.jpg and the back is pa_10XXXX00001.jpg. I had no hand in the nameing scheme.
My goal is to make a batchscript that merges the 2 corresponding .jpgs of each patient horizontally and automatically puts them in a different folder, so that I don't have to do it manually with something like MS Paint.
For example like this:
\images
\merged
\2017-08-21
\pa_102165_merged.jpg
\2017-06-14
\pa_101545_merged.jpg
\pa_104761_merged.jpg
\pa_107514_merged.jpg
\2017-03-73
\pa_109631_merged.jpg
\pa_108624_merged.jpg
I'm working on Windows 10 and found two promising methods so far but fail to comprehend how to make this into a batch file or something like it.
IrfanView Thumbnails
1. Mark the 2 corresponding .jpgs
2. File>Create contact sheet from selected files...
3. Create
4. File>Save as... in destination folder which i have to create for every day
which is faster than merging them by hand but would consume multiple workdays to do for all the pairs
and...
ImageMagic in Windows cmd
C:\Users\me\doctor\Images\test\images\2016-03-31>convert pa_102165.jpg pa_10216500001.jpg +append pa_102165_merged.jpg
This produces the merged .jpeg in the same folder the input images are in. This looks more promising but I fail to grasp how I could automate this process given the nameing scheme and the folder structure.
Thanks for taking the time to read this! I'm happy for every input you have!
This should get you fairly close. Essentially it is using the power of the FOR command modifiers to extract the base file name and file extension. The FOR /F command is capturing the output of the DIR command that is piped to the FINDSTR command. We are doing that so we only grab files with the file mask of pa_######.jpg
Once we have that we use the command modifiers with the IF command to make sure the 00001 file exists. If it does exist then it will execute the convert command. For the sake of making sure the code is performing correctly I am just ECHOING the output to the screen. If the output on the screen looks correct then remove the ECHO so that the CONVERT command executes.
#echo off
CD /D "C:\Users\me\doctor\Images\test\images"
FOR /F "delims=" %%G IN ('DIR /A-D /B /S PA_*.jpg ^|findstr /RIC:"pa_[0-9][0-9][0-9][0-9][0-9][0-9]\.jpg$"') DO (
IF EXIST "%%~dpnG00001%%~xG" (
ECHO convert "%%G" "%%~dpnG00001%%~xG" +append "%%~dpnG_merged%%~xG"
)
)
This task could be done with IrfanView with the following batch file stored in the directory containing the folder images.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IrfanView=%ProgramFiles(x86)%\IrfanView\i_view32.exe"
set "SourcePath=%~dp0images"
set "TargetPath=%~dp0merged"
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe /R "%SourcePath%" pa_10????.jpg 2^>nul') do for %%J in ("%%~dpI.") do (
if not exist "%TargetPath%\%%~nxJ\%%~nI_merged%%~xI" if exist "%%~dpnI00001%%~xI" (
if not exist "%TargetPath%\%%~nxJ\" md "%TargetPath%\%%~nxJ"
if exist "%TargetPath%\%%~nxJ\" (
echo Merging "%%~nxJ\%%~nxI" and "%%~nxJ\%%~nI00001%%~xI" ...
"%IrfanView%" /convert="%TargetPath%\%%~nxJ\%%~nI_merged%%~xI" /jpgq=95 /panorama=(1,"%%I","%%~dpnI00001%%~xI"^)
)
)
)
endlocal
There must be customized the fully qualified file name of IrfanView in the third line. There can be modified also the percent value of option /jpgq which defines the quality of the output JPEG file.
The command WHERE searches recursive in subdirectory images of the directory containing the batch file for files matching the wildcard pattern pa_10????.jpg with ignoring all other files. The found file names are output with full path and this list of file names is captured by FOR and processed line by line after WHERE finished. WHERE is executed in this case by one more cmd.exe started in background with option /c and the command line within ' as additional arguments and not by cmd.exe processing the batch file.
Read the Microsoft documentation 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 where command line with using a separate command process started in background.
Each image file with full name (drive + path + name + extension) is assigned one after the other to the loop variable I. For each file name one more FOR loop is used which processes just the full path to the current image file to assign this path with a dot appended to loop variable J. The dot at end means current directory, i.e. the directory containing current image file to process.
There is next checked with the first IF condition if for that image file does not exist already a matching pa_10????_merged.jpg file in which case there is nothing to do for the current image file. That means the batch file can be executed on same folder as often as wanted because of it runs IrfanView only for the source JPEG files for which the appropriate target JPEG file does not exist already.
The second IF condition checks if the back image exists also in the directory of current front image as otherwise nothing can be merged at all.
There is next checked with the third IF condition if the target directory exists already and this directory is created if that is not the case.
The last IF condition checks once again the existence of the target directory and if that exists now as expected, IrfanView is called with the appropriate options to create the merged image file in the target directory with the appropriate file name.
The closing round bracket ) on IrfanView command line must be escaped with ^ to be interpreted literally by cmd.exe to pass this closing parenthesis to IrfanView instead of interpreting it as end of one of the command blocks opened with ( above.
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 /? ... explains %~dp0 ... drive and path of argument 0 which is the batch file path always ending with a backslash
echo /?
endlocal /?
for /?
if /?
md /?
setlocal /?
where /?
Double click on the text file i_options.txt in program files folder of IrfanView for the description of the IrfanView options as used in the batch file.
I have a text file that contains names of all the files in my directory followed by its date.
Is it possible in batch/bash to extract those files names from the text file and its date based on a value on the string.
I have already checked Extracting strings from text file
but this does not answer my query. I have also checked numerous others including Get specific string from a text file using batch command and seems to hit a dead end as it doesn't get all the lines from the whole text file.
a typical string/file name looks like this
5f367f72-9e2f-4f89-b3d6-2cdafed17d94_IRO_RMUSI_SONG_TimayaKingPerryy_KomKom.mxf_A1.MXF,25/07/2019 05:47:24
The identifier is IRO. i have more files in the text file as well but I want it to be able to look at the text file, find everything that has the identifier and make a new text file with the IRO file and date populated.
There are about 150,000 +/- line of string so manually doing this wont be easy.
If its possible to be done in a batch-file i would appreciate it.
That's quite easy if you think about it. Filter your file with findstr "_IRO_"), then split the filename from the date with a for /f loop (according to your example, they are delimited with a comma):
(for /f "delims=," %%a in ('type "names.txt" ^|findstr "_IRO_"') do #echo %%a) > "newnames.txt"
Note: to execute it directly from a command line instead of in a batch file, replace every %%a with %a.
I'm trying to merge some csv files. I do it on Windows with cmd, like type *.csv >> or with a batch file, containing
echo. > all.csv
for %%a in (*.csv) DO copy /b alle.csv+%%a all.csv
On one computer (win7x64) is merging no problem. But on another one (same win7x64) all diacritical characters (german: äüöß) are broken - instead of them there are only ´,,´.
The source files, which should be merged, have healthy diacritical characters - i open them with Notepad++ and Excel, as ANSI or Unicode - everything is OK.
How can i adjust the file merging to save diacritical signs?
I believe there are several issues contributing to the unexpected results:
You try to create an empty file by echo. > all.csv, but this actually results in a file containing a SPACE, followed by a line-break (CR + LF), ANSI-encoded. So you may have files that are differently encoded, which can cause troubles.
To truly create an empty file, use rem/ > all.csv, break > all.csv, type nul > all.csv or copy /Y nul all.csv.
When combining files with copy, it can be problematic when the destination file is also one of the source files. When it is the first source file, the data of every other source files are appended; when it is not the first of the source files, an overwrite prompt may appear (unless you specify /Y) and data may be lost. Since you have given *.csv as the source file, we do actually not know which source file is enumerated first, so it could or may not be all.csv. So to avoid such trouble, you better delete the destination file before copying rather than create an empty file, like del all.csv.
Supposing you have Unicode files, they begin with a two-byte header 0xFF + 0xFE. When combining such files using copy /B, you have multiple of these headers within the file. To overcome this, do copy /A but within a Unicode cmd instance initiated by cmd /U:
cmd /U /C del all.csv ^& copy /A *.csv all.csv
copy /b *.csv all.txt & ren all.txt all.csv
or
2>nul del all.csv & copy /b *.csv all.csv
The type command can make some changes that could interfere in the process. Better use copy /b (with or without the for), but ensure the file being generated is not present or selected to avoid it being included as source in the process.
You should also ensure all your files have the same encoding. If some of them are Unicode/UTF-? with BOM and some not, depending of what the first file is selected, you could end with bad formated data.
Background
I find myself often copying file paths to the clipboard, which is somewhat cumbersome to do from Windows Explorer.
So I wrote a little .bat file to put into the %APPDATA%\Microsoft\Windows\SendTo\ folder utilising the CLIP executable to copy a list of the selected file paths to the clipboard. This file consists only of a single line:
echo|set /p= "%*" | clip.exe
Which works quite nicely, I can select one or more filenames in Explorer, right-click on them and "Send To" the .bat file, which copies them to the clipboard. Each file path is complete and separated from the others by a space character.
Question
Sometimes, I don't want to copy a list of the full file paths, but would prefer to have a list of just the filenames with their extensions. I know how to do that conversion for single file paths, using the %~nx syntax as described here or here.
I tried different combinations of these but can't seem to find a workable solution for my list of paths. The following code echos the filenames correctly:
for %%F in (%*) do echo %%~nxF
...but how do I combine them to pass through to CLIP? Do I have to do string concatenation? Maybe in a subroutine to be called, or is there a more elegant solution?
The following will put each file name on a separate line within the clipboard:
#(for %%F in (%*) do #echo %%~nxF)|clip
If you prefer, the following will put a space delimited list of file names on a single line, with quotes around each file name.
#(for %%F in (%*) do #<nul set /p =""%%~nxF" ")|clip
Couldn't you just:
echo|set /p= "%~nx*" | clip.exe