batch removing padding white space - batch-file

I have a batch file that will read values from a .ini file line by line, and use these variables to do other steps.
config.ini
Folder=Z:\task\first task\archive\
FileName=aFileName.xlsx
break
Then in my batch file i read the lines like the following and copy it to somewhere else like the following: job.bat
for /f "tokens=1,2 delims==" %%a in (.\config.ini) do (
if %%a==Folder set Folder=%%b
if %%a==Format set Format=%%b
if %%a==break (
call :copyFile
)
)
GOTO :EOF
:copyFile
xcopy %Folder%%Filename% D:\abc\ /f /y
GOTO :EOF
so the problem is at %Folder%%Filename%
for some reason, there is a space between the folder path and File name so it turns out to be
Z:\task\first task\archive\ aFileName.xlsx
I have tried to echo the variable after reading from file line by line and do echo "%Folder%" and i can see there are white space at the end of the variable. is there anyways to trim ONLY the end of the variable? I have tried some suggestions online, but it seems like it would also remove the white space within the variable, as you can see I do have a white space in the folder variable
Also, is there a way to exclude some of the charaters during string replacement. eg:
set filename=name_mm.txt
call set replaceName=%filename:mm=01%
this will replace the character mm to 01 in result of name_01.txt
but in another case, i got a filename that also have mm inside eg:
set filename=communicate_mm.txt
in this case, is there a way to ONLY replace the mm add the end? I know i could've replace the string _mm instead of mm, but there are other cases that the file name format like yyyymmdd.

:copyFile
if "%folder:~-1%" equ " " set "folder=%folder:~0,-1"&goto copyfile
xcopy %Folder%%Filename% D:\abc\ /f /y
would probably cure the spaces-at the-end problem.
You really shouldn't ask two questions in one - at the price charged per question, it's not expensive.
But for the second question, why no replace _mm instead of mm?
But if you want the last 3 characters, then
%varname:~-3%
and all but the last 3
%varname:~0,-3%
which is documented in the set instruction - try set /? from the prompt.

Related

Remove certain characters in a string using Windows command line

I have a text file having the string:
pub:
04:d6:b6:f2:98:ff:94:d8:3c:36:ad:5f:86:40:aa:
d1:5a:e1:87:5d:55:9d:ad:8b:2b:fc:18:e7:bb:47:
7f:9f:9a:62:c6:19:3a:9e:65:62:4e:5e:98:6d:db:
0e:7d:f9:22:a3:ca:cb:12:b2:ed:eb:14:0c:b3:31:
59:02:17:6d:6a
I need to remove the 04 from the beginning of this and also remove the ':' from between the characters and print it like this, in a single line:
d6b6f298ff94d83c36ad5f8640aad15ae1875d559dad8b2bfc18e7bb477f9f9a62c6193a9e65624e5e986ddb0e7df922a3cacb12b2edeb140cb3315902176d6a
How can I do that using Windows commands?
quite straightforward:
#echo off
setlocal enabledelayedexpansion
set "first=true"
(for /f "eol=p delims=" %%a in (input.txt) do (
set "line=%%a"
if defined first (set "line=!line:~2!" & set "first=")
<nul set /p ".=!line::=!"
))>output.txt
Read the input file line by line.
Use a flag (first) to check for first line and remove the first two chars.
Remove the colons and
use <nul set /p to write without a line break.
Edit as it turned out in comments, your file has actually just one long line. This changes the way for processing to:
for /f %%a in (input.txt) do set "line=%%a"
set "line=%line:pub:04:=%"
set "line=%line::=%"
echo %line%
Note: variables can just hold a certain amount of data, so this apporach will fail, when the line exceeds this limit.
Your question is pretty confusing. You first say: "I have a text file having the string:", but the example data have six lines that could be taken as six strings, so at this point we have no idea of what the real data format is. Perhaps a single long line that you write here in six parts?
Next, you said "I need to remove the 04 from the beginning of this", but what happen if the data have not a 04 at the beginning? Perhaps you want to remove the first element even if it is not a 04?
In this way, we must assume several points in order to try to write a working solution.
The Batch file below read a file with several lines, remove the first line (even if it does not contain pub:), and remove the first colon-separated element (even if it is not 04):
#echo off
setlocal EnableDelayedExpansion
rem Read all lines, excepting the first one:
set "string="
for /F "skip=1" %%a in (input.txt) do set "string=!string!%%a"
rem Remove the first element:
set "string=%string:*:=%"
rem Show the rest, removing colons:
echo %string::=%
In this code there are other assumptions that are implicit in the way the commands work, like lines that does not contain spaces nor exclamation marks. Of course, if the real data file have a different format, this program will fail...

Determine filename length from a batch file

I need to work two things into a .bat file I am working on for a little project. First things first, I have to know if any filename contained into the same folder (recursively) I launch my .bat in is any longer than 100 characters. If so, I need to make it 92 characters long and keep the extensions.
For example, I have this filename:
IncrediblyLongFileNameIAmSorryForThisItLooksLikeSomeDamnSpamJesusIAintEvenCloseTo100yetalmostwaitforitYEAH.omg
The above filename is 110 characters. I need to keep the extension, therefore the program should rename the file as this:
IncrediblyLongFileNameIAmSorryForThisItLooksLikeSomeDamnSpamJesusIAintEvenCloseTo100yetalmos.omg
So far, my main problem is that I don't know how to work with filename strings in batch. I used this code:
#echo off & setlocal enableextensions
FOR /R %%i IN (*.*) DO (
ECHO %%~nxi
FOR /f "delims=:" %%a in ('
^(echo."%%~nxi"^& echo.^)^|findstr /o .'
) DO set lenght=%%a-5
echo The length of "%%~nxi" is %lenght%
)
endlocal & goto :EOF
But I can't SET inside a FOR, and it can't do basic math either (i.e. it can't do the -5 operation).
The second thing, which I believe should be easier once the first one is done, is simply to compare all the filenames in the folder (recursive, once again) and make sure no filenames are the same. If the program finds any filenames that are the same, the second occurrence should be renamed to add something like l1l at the end. (I can't use parentheses here, therefore I use two ls instead to cover the number.) The only thing you need to take care of is the file extensions, because I can't add anything after the file extensions, lest they become unusable.
Can anyone offer explanations for how to accomplish this? I would really like to be able to work this out myself, but I simply lack experience in batch programming.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "tempfile=%temp%\##fn##.92"
ECHO ::>"%tempfile%"
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\*" '
) DO (
SET "fullname=%%a"
SET "name=%%~na"
SET "ext=%%~xa"
CALL :chgname
)
del "%tempfile%"
GOTO :EOF
:chgname
:: Proposed new name part - first 92 characters of existing name
:: also prepare for adding modifier
SET "newname=%name:~0,92%"
SET /a modifier=0
:modl
:: See whether this name has already been found
ECHO %newname%%ext%|FINDSTR /b /e /i /g:"%tempfile%" >NUL
IF ERRORLEVEL 1 GOTO makechange
:: existing name - modify it
SET "newname=%name:~0,92%#%modifier%#"
SET /a modifier+=1
GOTO modl
:makechange
IF "%name%" NEQ "%newname%" ECHO REN "%fullname%" "%newname%%ext%"
>>"%tempfile%" ECHO %newname%%ext%
GOTO :eof
Reasonably simple problem.
Get a directory-list in basic form (full-filename only) and apply the full filename, name part and extension part to appropriately-named variables.
Manipulate the filename to a new name consisting of the first 92 characters of the original name part. Anticipate the need to modify this new name by establishing a modifier to optionally be applied.
See whether the proposed new name already exists in the temporary file of NEW names already processed. If not found on that file, safe to rename (if required) and record name used.
If the filename has already been used, modify it to the original first 92+ "#anumber#", increment the modifier in anticipation and try again.
Only two comments required further - first, I used # rather than ! because ! has a special meaning to batch. Second, writing :: to the tempfile (the name of the tempfile is irrelevant - I chose one that's unlikely to exist...) means that findstr doesn't complain because the file is empty, but :: can't possibly be a real filename.
The /b /e /i options to findstr mean that the name echoed in must exactly match a line (matches both /b - begin and /e - end) but /i - case is irrelevant.

Batch trim characters at the EOL

i would like to create a batch file that goes through txt files in a directory and every line that has #EXTINF in it, remove the last 15 characters..
basically if it is possible, i would like to trim the last 15-20 characters from any lines that is longer than a certain number. for some reason i have a software that if the line is too long, it will screw up the data.
thanks
See How can you find and replace text in a file using the Windows command-line environment? for various options to modify text files using Windows batch.
The following simple code uses REPL.BAT to truncate long lines that begin with #extinf (case insensitive) at 600 characters. Lines that are less than 600 characters are preserved in their entirety.
type test.txt|repl.bat "^(#extinf.{593}).*$" "$1" I>test.txt.new
move /y test.txt.new test.txt >nul
User231429 wrote: "i need the script to go through all files in a directory, and each line that starts with #extinf, remove XX number of characters from the end."
The Batch file below do precisely that:
#echo off
setlocal EnableDelayedExpansion
for %%f in (*.txt) do (
(for /F "usebackq delims=" %%a in ("%%f") do (
set "line=%%a"
if "!line:~0,7!" equ "#extinf" set "line=!line:~0,-XX!"
echo !line!
)) > "%%~Nf.new"
)
REM del *.txt
REM ren *.new *.txt
Note that you must replace XX by a number in the long if command.
Test this program and check the result in *.NEW files. If the result is correct, remove REM part from two last lines.
This program remove exclamation marks from the file. This detail may be fixed, if required.

Batch file to read first line of text that hasn't been used, and then mark as used

I have a requirement to, within a windows batch file, read the first available line from a text file, pass it to a variable and mark the name\line as used
An example of the file is below.
apple
pear
orange
The script would start with 'apple', pass 'apple' to a variable to be used later in the script (I know how to do that bit), and then write back that line to read &apple, the '&' works as a marker to say it's been used.
The file would then look like:
&apple
pear
orange
the next time the batch file is run it would take 'pear', pass it to a variable and mark it with a & making it look like:
&apple
&pear
orange
I started by trying to find '&' and then trying to move to the next line, but I'm failing after about 12 hours of trying. This is what I got so far .. not much:
for /f "tokens=1" %l in ('name.txt') do (Find /v "&" /v "^---- ^$") (For /F %n in (%l) do (set NewName=%n))
Thanks
Running this on the.file would modify each line in turn;
#echo off
setlocal enabledelayedexpansion
type nul > the.file.temp
set last=
for /F "tokens=*" %%A in (the.file) do (
set line=%%A
if "!line:~0,1!" neq "&" if "!last!" equ "" (
set last=!line!
set line=^&!line!
)
echo !line! >> the.file.temp
)
echo last value is !last!
type the.file.temp > the.file
(If the line does not begin with & and the variable last is empty, put the line in last & modify line with a leading &. Always append line to a temp file, renaming when done)
Alex k. has a good answer that is probably fine for most situations. (I upvoted.)
However, it will corrupt any text containing !. That limitation can be fixed by toggling delayed expansion on and off within the loop.
The solution is likely to be fast enough for most reasonably sized files. But a FOR loop can become quite slow for large files.
I tested a 190kb file containing 2817 lines, and the Alex K. solution took 20 seconds for one run.
Here is a completely different solution without using any loops that processes the same 190kb file in 0.07 seconds - 285 times faster :)
#echo off
setlocal enableDelayedExpansion
set "file=test.txt"
findstr /bv "$ &" "%file%" >"%file%.available"
set "var="
<"%file%.available" set /p "var="
if defined var (
>"%file%.new" (
findstr /b "&" "%file%"
<nul set /p "=&"
type "%file%.available"
)
move /y "%file%.new" "%file%" >nul
)
del "%file%.available"
echo var=!var!
Update: As requested in comment, here is a heavily commented version of the code.
#echo off
setlocal enableDelayedExpansion
:: Define the file to process
set "file=test.txt"
:: Write the unused lines to a temporary "available" file. We don't want any
:: empty lines, so I strip them out here. There are two regex search strings;
:: the first looks for empty lines, the second for lines starting with &.
:: The /v option means only write lines that don't match either search string.
findstr /bv "$ &" "%file%" >"%file%.available"
:: Read the first available line into a variable
set "var="
<"%file%.available" set /p "var="
:: If var defined, then continue, else we are done
if defined var (
REM Redirect output to a "new" file. It is more efficient to redirect
REM the entire block once than it is to redirect each command individulally
>"%file%.new" (
REM Write the already used lines to the "new" file
findstr /b "&" "%file%"
REM Append the & without a new line
<nul set /p "=&"
REM Append the unused lines from the "available" file. The first appended
REM line is marked as used because of the previously written &
type "%file%.available"
)
REM Replace the original file with the "new" content
move /y "%file%.new" "%file%" >nul
)
:: Delete the temp "available" file
del "%file%.available"
:: Display the result
echo var=!var!
I haven't tested this, but I just realized I could have written the line that writes the available lines to look for lines that start with a character other than &:
findstr "^[^&]" "%file%" >"%file%.available"

How to use wildcards in Batch programming?

I am trying to move certain groups of files using wildcards to a folder that is created by the group's filename. The names of the files are stored in "events.txt".My batch file is running uptil the last line. It is displayed that my syntax is not correct.
echo off
for /F "tokens=*" %%A in (events.txt) do call :makemove %%A
pause
exit
:makemove
set f=%1
set file=%f:~0,-4%
md X%file%
set dest=C:\Users\sony\Desktop\X%file%
move /y "C:\Users\sony\Desktop\*%file%*.*" "%dest%"
Seems like there are whitespace characters after
set file=%f:~0,-4%
line.
This causes the last line of your script evaluate to
move /y "C:\Users\sony\Desktop\*foobar *.*" "C:\Users\sony\Desktop\Xfoobar "
and messes paths up.
Like Helbreder pointed out, there is a space after set file=%f:~0,-4%.
To avoid this type of problems you can use the extended syntax of SET.
set "file=%f:~0,-4%"
The surrounding quotes will ensure that only all characters until the last quote are part of the string.
The quotes itself are not part of the string.
So even this would work
set "file=%f:~0,-4%" the spaces and this text will be removed
Another positive effect from the quotes is that they will avoid problems with special characters in the filename, like in Cat&Dog.
So your code should look like
#echo off
for /F "tokens=*" %%A in (events.txt) do call :makemove %%A
pause
exit
:makemove
set "f=%~1"
set "file=%f:~0,-4%"
md "X%file%"
set "dest=C:\Users\sony\Desktop\X%file%"
move /y "C:\Users\sony\Desktop\*%file%*.*" "%dest%"

Resources