findstr not working as expected - cmd

I am trying to find last line in a text file using the regex ^.*\z, it's working fine in notepad++ but when I try it in cmd using findstr /R "^.*^Z" file.txt not working.

Open a command prompt window and run findstr /?. The output help explains what FINDSTR supports. The regular expression feature is limited in FINDSTR. It does not support all the features as supported by Boost Perl Regular Expression library used by many text editors in various versions.
This batch code could be used to get last non empty line from a file assigned to an environment variable:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LastLine="
if exist "file.txt" for /F "usebackq eol= delims=" %%# in ("file.txt") do set "LastLine=%%#"
echo Last line is: "%LastLine%"
endlocal
Command FOR skips all empty lines and by default also all lines starting with a semicolon. For that reason eol= is used to define form-feed control character as end of line. In case of last line of file surely never starts with ; it would be best to remove eol= from the FOR command line.
In case of file to process always has at least X lines, it would make sense to add to the FOR options after usebackq the option skip=X to skip the first X lines of the file for faster processing.
For details on command FOR open a command prompt window and run for /?.

Related

Trying to rename all files ending with "VA.pdf" to "PA.pdf" using batch code

Hello I am trying to rename all files ending with "VA.pdf" to "PA.pdf" using batch code
I tired this code but it is not working
REN *VA.pdf *PA.pdf
Appreciate any help
There can be used for this file renaming task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist "*!*VA.pdf" goto ExtendedVersion
setlocal EnableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir *VA.pdf /A-D-L /B 2^>nul') do (
set "FileNamePDF=%%~nI"
set "FileNameNew=!FileNamePDF:~0,-2!PA%%~xI"
if not exist "!FileNameNew!" ren "!FileNamePDF!%%~xI" "!FileNameNew!"
)
endlocal
goto EndBatch
:ExtendedVersion
echo INFO: Extended version required because of a PDF file with exclamation marks.
for /F "eol=| delims=" %%I in ('dir *VA.pdf /A-D-L /B 2^>nul') do (
set "FileNamePDF=%%~nI"
setlocal EnableDelayedExpansion
set "FileNameNew=!FileNamePDF:~0,-2!PA%%~xI"
if not exist "!FileNameNew!" ren "!FileNamePDF!%%~xI" "!FileNameNew!"
endlocal
)
:EndBatch
endlocal
There is defined first the required execution environment with the first two command lines.
The IF condition in the third command line quickly checks if there is any PDF file with case-insensitive VA in the file name before the file extension .pdf containing one or more exclamation marks in the file name. The extended version of the processing loop is required if this condition is true.
The standard version enables first required delayed expansion. Then a FOR loop is used which runs in background with Windows installed into C:\Windows:
C:\Windows\System32\cmd.exe /c dir *VA.pdf /A-D-L /B 2>nul
The internal command DIR of cmd.exe searches
in the current directory as defined by the process starting cmd.exe for processing the batch file
for just file names because of option /A-D-L (attribute not directory and not link)
matching case-insensitive the wildcard pattern *VA.pdf in long or short 8.3 name
and outputs in bare format because of option /B just the file names with file extension, but without file path.
An error message output to handle STDERR (standard error) on DIR does not find any file system entry matching the criteria is suppressed by redirecting this error message to the device NUL.
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 dir command line with using a separate command process started in background.
FOR respectively cmd.exe processing the batch file captures all output written to standard output stream of in background started cmd.exe and processes it line by line after started cmd.exe closed itself after finishing executing the command DIR.
FOR with option /F is used here to get a list of file names of *VA.pdf files loaded into memory of cmd.exe before really doing the file renames as otherwise it could happen especially on FAT drives (FAT32, exFAT) that some PDF files are skipped or processed more than once (on rename not possible).
FOR on using option /F ignores always empty lines which is no problem here as DIR with the used options does not output empty lines.
FOR would next split up the lines into substrings using horizontal tab and normal space as string delimiters, would look next if first tab/space separated string begins with a semicolon in which case it would also ignore the entire line for further processing, and would otherwise assign just the first tab/space separated string to the specified loop variable I before running the commands in body of FOR.
The default line splitting behavior is not wanted as PDF file names can contain one or more spaces. The usage of the option delims= defines an empty list of delimiters which turns off the line splitting behavior.
It is very unusual but nevertheless possible that a PDF file name begins with ; (semicolon). Such a file name should not be ignored by FOR. The option eol=| defines a vertical bar as end of line character which no file name can contain ever. Microsoft lists the characters not allowed in a file name on Windows file systems in the documentation about Naming Files, Paths, and Namespaces.
The current file name without file extension .pdf is assigned first to the environment variable FileNamePDF.
Next a string substitution is used to get from the string value of the environment variable FileNamePDF the file name without the last two characters VA concatenated with the string PA and the file extension .pdf assigned to the environment variable FileNameNew.
If there is not already a PDF file ending with PA in the file name before the file extension, there is next executed the command REN to rename the *VA.pdf file to *PA.pdf.
The command ENDLOCAL after the loop restores the previous environment before enabling delayed expansion and the command GOTO instructs the Windows Command Processor to continue processing the batch file with the command line below the label EndBatch which contains one more ENDLOCAL to restore the environment on starting the batch file processing.
The extended version is nearly the same as the standard version. The difference is that delayed variable expansion is not enabled on assigning the file name of the current VA.pdf file without the file extension to the environment variable FileNamePDF. That avoids interpreting the exclamation mark(s) in the file name as beginning/end of a delayed expanded variable reference resulting in a manipulation of the file name string before assigning it to the environment variable as it would happen with delayed expansion already enabled.
The extended version enables next delayed variable expansion inside the loop, does the same as the standard version and restores finally the previous environment before processing the next *VA.pdf file.
The extended version is slower because of the environment variables list copy and the other operations made in background by every execution of SETLOCAL as explained in full details in this answer. The command ENDLOCAL in the loop is required to avoid a stack overflow on processing lots of PDF files.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
echo /?
endlocal /?
for /?
goto /?
if /?
ren /?
set /?
setlocal /?

Capturing first 4 characters of a Windows command line output to variable

I'm trying to capture the first 4 characters of output from the following Windows command.
nltest /server:%COMPUTERNAME% /dsgetsite
What is normally returned would be:
SITEAdSiteName
This command completed successfully.
I've tried using the for /F command but can't seem to figure out how to strip everything else except the first 4 characters of what is returned.
I'm thinking using the for /F may not be the best way to accomplish this.
Are there other suggestions on how I many accomplish this?
I think my challenge is defining (or not) the delimiter to being any character, I've tried the *, but didn't seem to do it for me.
When I use this:
for /F "tokens=1-4 delims=*" %A in ('nltest /server:%COMPUTERNAME% /dsgetsite') DO echo %A
I get both output lines, sort of stumped here.
To store the first line of the output of nltest /server:%COMPUTERNAME% /DSGETSITE in variable LINE, use the following command line (use %%F instead of %F to use this in a batch file):
set "LINE=" & for /F %F in ('nltest /server:%COMPUTERNAME% /DSGETSITE') do if not defined LINE set "LINE=%F"
To return the first four characters, use sub-string expansion:
set "LINE=%LINE:~,4%"
echo %LINE%

Batch script to print last line of many files in a folder matching a file name pattern

I have multiple text files in a folder. I would like to print the last line of each file found in the folder matching the file name pattern *.Config and redirect those lines to a new text file.
The below script works for 1 text file. But at the moment I do a for loop for multiple text files and %lastline% prints always the same value.
#echo off & setlocal EnableDelayedExpansion
for /f %%i in ('dir /b *.Config') do (
for /r "delims==" %%a in (%%i) do (
set lastline=%%a
echo %lastline% is the last line of %%i >> vResult.txt
)
)
Use this batch code to get written into file vResult.txt in current directory the last line of each *.config file in current directory:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
del vResult.txt 2>nul
for %%I in (*.config) do (
for /F "usebackq delims=" %%L in ("%%I") do set "LastLine=%%L"
echo !LastLine! is the last line of %%I>>vResult.txt
)
endlocal
First command extensions as needed for the second FOR command line and delayed environment variable expansion as needed for echoing the last line of each file are enabled with second command line. Command extensions are enabled by default, but not delayed expansion.
Then a perhaps already existing vResult.txt is deleted with suppressing the error message output by command DEL to handle STDERR by redirecting it to device NUL in case of the file to delete does not exist.
The outer FOR searches for *.config files in current directory with hidden attribute not set. There is no need to use command DIR here except it would be necessary to find also hidden *.config files.
The inner FOR processes the lines of each *.config file found by the outer FOR loop. It is in general advisable to enclose the file name in double quotes and use usebackq to interpret the double quoted file name as file name and not as string to process in case of a *.config file contains a space character. delims= disables splitting each line up on spaces/tabs to get entire line.
As the environment variable LastLine is defined/modified within a command block, it is necessary to use delayed expansion as enabled at beginning with referencing the environment variable with exclamation marks instead of percent signs.
All environment variables referenced with percent signs of entire command block to execute on each iteration of outer FOR are replaced already by Windows command interpreter with current value of referenced environment variable before executing outer FOR command. This resulted on your batch code with ECHO command line additionally in wrong loop in replacing %lastline% by nothing before the outer FOR is executed the first time.
For debugging a batch file and to see what Windows command interpreter really executes after preprocessing the command lines and the command blocks, remove or comment out #echo off or change that line to #echo on, open a command prompt window, and run the batch file from within this console window by entering its name with full path enclosed in double quotes after changing the current directory to the directory on which the batch file should work.
A space character left of redirection operator >> is also output by command ECHO and therefore also written to the text file as trailing space which is the reason why the space character left of >> is removed here. The space character right of >> would be ignored, but is here also removed.
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 /?
endlocal /?
for /?
setlocal /?
set /?
And see also the Microsoft article Using command redirection operators.

How to remove a single character from the filename of a list of files in a folder using DOS command?

I have a list of files like these:
icone1.gif
icone2.gif
icone1.gif
icone11.gif
icone12.gif
icone13.gif
icone14.gif
icone15.gif
I want to remove 'e' from it so they will icon1.gif, icon2.gif and so on...
I tried this from the DOS Command Prompt:
ren icone*.gif icon*.gif
Didn't work.
Create a batch file in the folder by typing "notepad go.bat" at the command prompt and hitting enter and drop this in then save and exit notepad:
for %%i in ("*.gif") do (set fname=%%i) & call :rename
goto :eof
:rename
::Cuts off 1st five chars, then appends Icon and the remaining chars
ren "%fname%" "Icon%fname:~5%"
goto :eof
Double click the batch file in windows or from the command prompt type go and press enter
See How does the Windows RENAME (REN) command interpret wildcards? for rules that can explain why your command does not work.
Assuming all your file names have a digit after "icone" (really only care that you never have another "e" following "icone"), then the following one liner will work from the command line.
for /f "tokens=1* delims=eE" %A in ('dir /b icone*.gif') do #ren "%Ae%B" "%A%B"
Double up the percents if you put the command within a batch script.
For a really simple and robust solution, use my JREN.BAT regular expression renaming utility, pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.
jren "^(icon)e(.*\.jpg)" "$1$2" /i

Delete a Batch file variable in a text file

I am currently trying to delete a variable from a batch file which is in a text file
e.g. delete %variable%
where %variable% = "test"
So the batch script would delete the instance of "test" in the specified text file
Can this be done?
#echo off
setlocal enabledelayedexpansion
set variable=test
for /f "delims=" %%l in (foo.txt) do (
set "line=%%f"
echo !line:%variable%=!
)
To avoid potential special character issues with the string you are searching for, it may be better to just call findstr directly like this:
type input.txt | findstr /b /e /v "remove_line" > input_without_remove_line.txt
/b and /e together will only match if the "remove_line" is the only text on a line. /v will switch the output to only print all lines that do not match.
If you are sure you're not passing special characters, it is pretty easy to wrap that in a small batch and replace remove line with %1 or %* to use your passed parameters.
Unfortunately, you will need to use a temporary file - replacing the file in place doesn't work with the DOS output redirection.
If you were wanting to delete all instances of a specified word within any line, batch and findstr are probably not the way to do it. Look at sed, which can do much more and is freely available. If you can't install another utility, even vbscript using cscript would be a better way to do this than batch.

Resources