So I have a file with multiple lines of letters and numbers as shown:
a
1
h
7
G
k
3
l
END
I need a type of code that combines them together and preferably outputs it into a variable as shown:
var=a1h7Gk2l
Any help would be appreciated.
#echo off
setlocal enableDelayedExpansion
set "var="
for /f "usebackq" %%A in ("test.txt") do set var=!var!%%A
echo !var!
Edit
I assumed "END" does not physically exist in your file. If it does exist, then you can add the following line after the FOR statement to strip off the last 3 characters.
set "!var!=!var:~0,-3!"
Or, if you just want to put the result into a file (as opposed to storing it in memory for some purpose), you could do something like this:
#ECHO OFF
TYPE NUL >output.txt
FOR /F %%L IN (input.txt) DO (
IF NOT "%%L" == "END" (<NUL >>output.txt SET /P "=%%L")
)
ECHO.>>output.txt
The last command may be unnecessary, depending on whether you need the End-of-Line symbol at, well, the end of the line.
Related
I have 324 files on a Windows 10 machine which are named in the following pattern:
[7 Numbers] [Space] [Last name] [Space] [First name]
And I need them to be:
[Last name] [Space] [First name] [Space] [7 Numbers]
I have done some quick research and found that I could write a batch script utilizing the 'rename' function:
#echo off
rename “y:\*.txt” “???-Test1.*”
However, I was unable to find out how I can program the script to take the first 7 chracters and put them to the end.
Any help is appreciated.
Given the little detail on the exact formatting of your structures, i.e what happens in the event a surname has a split like van Halen which also now contains a space:
anyway, this will cater for the situation as you've mentioned only and not for names/surnames containing spaces.
#echo off
for /f "tokens=1-3*" %%i in ('dir /b /a-d *.txt ^| findstr /R "^[1-9]"') do echo ren "%%i %%j %%k" "%%~nk %%~nj %%~ni%%~xk"
Note this example will simply echo the command and not perform the actual rename. You need to test it first before you do the renaming. Once you are happy with the result printed to console, then remove echo from the line.
Note. findstr is important here as we need to only perform the action if the file starts with numbers. You can define the findstr filter even more if you want to be more specific. Here I just focused on numbers in the beginning of any .txt file considering no name or surname should start with a number., Unless you're 50cent or some other random rapper.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
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\t w o"
FOR %%b IN ("%sourcedir%\??????? * *.txt") DO FOR /f "tokens=1*delims= " %%u IN ("%%~nb") DO SET /a junk=0&SET /a "junk=1%%u" 2>nul&IF !junk! geq 10000000 IF !junk! leq 19999999 ECHO REN "%%b" "%%v %%u.txt"
GOTO :EOF
Please note that this routine uses delayedexpansion
The first for puts the absolute filename of each file matching the mask into %%b
The second partitions the name part of the filename (%%~nb) into that part before the first space (token 1) to %%u and the remainder (token *) to %%v
junk is then set to 0 and then reset to the value of 1%%u. set /a will leave junk unchanged (therefore, 0) if %%u is not a numeric string (the 2>nul suppresses the error message) so if %%u is numeric, junk will be set to 10000000 ... 19999999.
Use !junk! to access the run-time value of junk, check it is within range and if so, echo the ren required.
Remove the echo keyword before the ren after checking the resultant report to actually rename the files.
I have a batch file which copies some local files up to a google storage area using the gsutil tool. The gsutil tool produces a nice log file showing the details of the files that were uploaded and if it was OK or not.
Source,Destination,Start,End,Md5,UploadId,Source Size,Bytes Transferred,Result,Description
file://C:\TEMP\file_1.xlsx,gs://app1/backups/file_1.xlsx,2018-12-04T15:25:48.428000Z,2018-12-04T15:25:48.804000Z,CPHHZfdlt6AePAPz6JO2KQ==,,18753,18753,OK,
file://C:\TEMP\file_2.xlsx,gs://app1/backups/file_2.xlsx,2018-12-04T15:25:48.428000Z,2018-12-04T15:25:48.813000Z,aTKCOQSPVwDycM9+NGO28Q==,,18753,18753,OK,
What I would like to do is to
check the status result in column 8 (OK or FAIL)
If the status is OK then move the source file to another folder (so that it is not uploaded again).
The problem is that the source filename is appended with "file://" which I can't seem to remove, example
file://C:\TEMP\file_1.xlsx
needs to be changed into this
C:\TEMP\file_1.xlsx
I am using a for /f loop and I am not sure if the manipulation of the variables %%A is different within a for /f loop.
#echo off
rem copy the gsutil log file into a temp file and remove the header row using the 'more' command.
more +1 raw_results.log > .\upload_results.log
rem get the source file name (column 1) and the upload result (OK) from column 8
for /f "tokens=1,8 delims=," %%A in (.\upload_results.log) do (
echo The source file is %%A , the upload status was %%B
set line=%%A
set line=!line:file://:=! >> output2.txt echo !line!
echo !line!
)
The output is like this.
The source file is file://C:\TEMP\file_1.xlsx , the upload status was OK
The source file is file://C:\TEMP\file_2.xlsx , the upload status was OK
I'm expecting it to dump the altered values out into a new file but it is not producing anything at the moment.
Normally I would extract from a specific character to the end of the string with something like this but it doesn't work with my For/f loop.
%var:~7%
Any pointers or a different way of doing it greatly appreciated.
Since the part to remove seems fixed it is easier to use substrings.
Also using for /f "skip=1" evades he neccessity of the external command more +1 and another intermediate file.
#echo off & setlocal EnableDelayedExpansion
type NUL>output2.txt
for /f "skip=1 eol=| tokens=1,8 delims=," %%A in (.\upload_results.log) do (
echo The source file is %%A , the upload status was %%B
set "line=%%A"
set "line=!line:~7!"
echo(!line!>>output2.txt
echo(!line!
)
File names and paths can contain also one or more exclamation marks. The line set line=%%A is parsed by Windows command processor a second time before execution with enabled delayed expansion. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? Every ! inside the string assigned to loop variable A is on this line interpreted as begin or end of a delayed expanded environment variable reference. So the string of loop variable A is assigned to environment variable line with an unwanted modification if file path/name contains one or more exclamation marks.
For that reason it is best to avoid usage of delayed expansion. The fastest solution is for this task using a second FOR to get file:// removed from string assigned to loop variable A.
#echo off
del output2.txt 2>nul
for /F "skip=1 tokens=1,8 delims=," %%A in (upload_results.log) do (
echo The source file is %%A , the upload status was %%B.
for /F "tokens=1* delims=/" %%C in ("%%~A") do echo %%D>>output2.txt
)
Even faster would be without the first echo command line inside the loop:
#echo off
(for /F "skip=1 delims=," %%A in (upload_results.log) do (
for /F "tokens=1* delims=/" %%B in ("%%~A") do echo %%C
))>output2.txt
The second solution can be written also as single command line:
#(for /F "skip=1 delims=," %%A in (upload_results.log) do #for /F "tokens=1* delims=/" %%B in ("%%~A") do #echo %%C)>output2.txt
All solutions do following:
The outer FOR processes ANSI (fixed one byte per character) or UTF-8 (one to four bytes per character) encoded text file upload_results.log line by line with skipping the first line and ignoring always empty lines and lines starting with a semicolon which do not occur here.
The line is split up on every occurrence of one or more commas into substrings (tokens) with assigning first comma delimited string to specified loop variable A. The first solution additionally assigns eighth comma delimited string to next loop variable B according to ASCII table.
The inner FOR processes the string assigned to loop variable A with using / as string delimiter to get assigned to specified loop variable file: and to next loop variable according to ASCII table the rest of the string after first sequence of forward slashes which is the full qualified file name.
The full qualified file name is output with command echo and appended either directly to file output2.txt (first solution) or first to a memory buffer which is finally at once written into file output2.txt overwriting a perhaps already existing file with that file name in current directory.
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.
del /?
echo /?
for /?
See also the Microsoft article about Using command redirection operators for an explanation of the redirections >, >> and 2>nul
Problem with the file is that it sometimes contains a blank line and so the size is not zero. I tried this but as it has an empty line so it returns 1 instead of 0. Any suggestions how to tackle it?
set /a varTestPoints=0
for /f %%a in ('type "file.txt"^|find "" /v /c') do set /a varTestPoints=%%a
The size can be checked with
for %%a in ("file.txt") do echo %%~za
where %%~za is the size of the file referenced by %%a
To test if the file only contains blank lines any of these commands can be used
(for /f usebackq^ eol^= %%a in ("file.txt") do break) && echo has data || echo empty
(for /f "usebackq eol= " %%a in ("file.txt") do break) && echo has data || echo empty
If the for /f can not find lines with data, it raises an error that can be checked with the && and || conditional execution operators
note as aschipfl points, in the original code that checks for blank lines the default behaviour in for /f that skips lines that start with a semicolon will make the test fail in the lines in the file that start with ;. Now the code also handles this case by two different ways.
In the first command, eol clause is disabled by assigning it an empty list or delimiters.
The second command assigns a space to eol. While it seems that we simply have changed the problematic character, when the lines are parser by the for /f tokenizer, the delims clause has precedence over the eol (more information here), so spaces will be removed as delimiters before they can be seen as eol.
A file with a single blank line will be 2 bytes long (CR, LF). You can detect this by checking if the total file size is less than or equal to 2.
for %%a in (file.txt) do if %%~za LEQ 2 echo File has no more than 2 bytes
This may not work for other files that have more text, but still consist entirely of whitespace and thus appear "empty". For example, a file containing a single tab followed by a newline would have 3 bytes. You may be able to adjust your definition of a "blank" file and adapt the code accordingly.
The solution above won't work if your definition of an "empty" file is one that contains only whitespace, regardless of length. Instead, you can use for /F to parse the file. When reading a file, for /F only matches lines that contain non-whitespace characters. If it finds one, then the file is not "blank".
set "fileIsBlank=1"
for /F %%a in (file.txt) do set "fileIsBlank=0"
if %fileIsBlank% EQU 0 echo File has non-blank lines in it..
If I get my parameter with %1 and it is "Server" how can I add a + sign after every letter?
So my result would be "S+e+r+v+e+r"?
I think Batch file to add characters to beginning and end of each line in txt file this is a similar question but I don't know how to change the code for this purpose.
Any help would be great!
I'm pretty sure this has been asked and answered before, but I couldn't find it.
There is a really cool (and fast) solution that I saw posted somewhere. It uses a new cmd.exe process with the /U option so output is in unicode. The interesting thing about the unicode is that each ASCII character is represented as itself followed by a nul byte (0x00). When this is piped to MORE, it converts the nul bytes into newlines!. Then a FOR /F is used to iterate each of the characters and build the desired string. A final substring operation is used to remove the extra + from the front.
I tweaked my memory of the code a bit, playing games with escape sequences in order to get the delayed expansion to occur at the correct time, and to protect the character when it is appended - all to get the technique to preserve ^ and ! characters. This may be a new twist to existing posted codes using this general technique.
#echo off
setlocal enableDelayedExpansion
set "str=Server bang^! caret^^"
set "out="
for /f delims^=^ eol^= %%A in ('cmd /u /v:on /c echo(^^!str^^!^|more') do set "out=!out!+^%%A"
set "out=!out:~1!"
echo Before: !str!
echo After: !out!
--OUTPUT---
Before: Server bang! caret^
After: S+e+r+v+e+r+ +b+a+n+g+!+ +c+a+r+e+t+^
This batch file should do it:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET Text=%~1
SET Return=
REM Batch files don't have a LEN function.
REM So this loop will process up to 100 chars by doing a substring on each.
FOR /L %%I IN (0,1,100) DO (
CALL SET Letter=!Text:~%%I,1!
REM Only process when a letter is returned.
IF NOT "!Letter!" == "" (
SET Return=!Return!+!Letter!
) ELSE (
REM Otherwise, we have reached the end.
GOTO DoneProcessing
)
)
:DoneProcessing
REM Remove leading char.
SET Return=%Return:~1,999%
ECHO %Return%
ENDLOCAL
Calling with Test.bat Server prints S+e+r+v+e+r to the console.
I am trying to create a batch file that will edit a text file to remove lines that contain a certain string and remove the line directly after that.
An example of this file would look like this:
LINE ENTRY KEEP_1 BLA BLA
END
LINE ENTRY REMOVE_1 FOO BAR
END
LINE ENTRY REMOVE_2 HELLO WORLD
END
LINE ENTRY KEEP_2 CAT DOG
END
After running the batch script I require the new file to contain
LINE ENTRY KEEP_1 BLA BLA
END
LINE ENTRY KEEP_2 CAT DOG
END
where any line containing REMOVE_ has been deleted, as well as the corresponding 'END' line.
I have tried using the technique found here to remove the lines containing the string but it does not appear to be possible to include characters such as \r\n to check for and include the 'END' in the search. I can't do this as 2 seperate FINDSTR commands as I still require the 'END' text to be kept for the other two entries.
Using findstr /v REMOVE_ leaves me with the following:
LINE ENTRY KEEP_1 BLA BLA
END
END
END
LINE ENTRY KEEP_2 CAT DOG
END
and using findstr /v "REMOVE_*\r\nEnd" does not seem to work at all.
Just to confirm each line is definitely terminated with \r\n.
Any help on this issue would be greatly appreciated.
The following batch script should do what you want:
#echo off
setlocal enabledelayedexpansion
set /A REMOVE_COUNT=1
if "%~2"=="" (
echo Usage: %~n0 search_str file
echo remove lines that contain a search_str and remove %REMOVE_COUNT% line^(s^) directly after that
exit /b 1
)
set "SEARCH_STR=%~1"
set "SRC_FILE=%~2"
set /A SKIP_COUNT=0
for /F "skip=2 delims=[] tokens=1,*" %%I in ('find /v /n "" "%SRC_FILE%"') do (
if !SKIP_COUNT! EQU 0 (
set SRC_LINE=%%J
if defined SRC_LINE (
if "!SRC_LINE:%SEARCH_STR%=!" == "!SRC_LINE!" (
echo.!SRC_LINE!
) else (
set /A SKIP_COUNT=%REMOVE_COUNT%
)
) else (
rem SRC_LINE is empty
echo.
)
) else (
set /A SKIP_COUNT-=1
)
)
The number of lines to be removed after a matched line can be configured by setting the REMOVE_COUNT variable.
The script also handles files with empty lines correctly by using a trick: The find command is used to prefix all lines with line numbers. That way the for command will not skip empty lines.
findstr operates line-wise. You cannot do anything with it that spans more than a single line.
In any case, you're in for a world of pain if you do this with batch files. While you certainly can loop through the file and only output certain lines, this would look kinda like the following:
set remove=
for /f %%x in (file.txt) do (
if not defined remove (
echo %%x|findstr "REMOVE" >nul 2>&1 && set remove=1
if not defined remove echo.%%x
) else (
set remove=
)
)
(untested, but might work). The problem here is twofold: for /f removes any empty lines from the output so if your file had them before you won't have them afterwards. This may or may not be a problem for your specific case. Another problem is that dealing with special characters can get hairy. I give no guarantee that the above works as it should for things like >, <, &, |, ...
Your best bet in this case, if you need to run it on almost any Windows machine, would probably be a VBScript. The string handling capabilities are much more robust there.