My text file include with 23 lines (lines include: !#$:/;" )
How can i only display line 3? in or 7? or 19?
I tried all commands was in stackoverflow
Example:
setlocal enabledelayedexpansion
#echo off
for /f "delims=" %%i in (mytext.txt) do (
if 1==1 (
set first_line=%%i
echo !first_line!
goto :eof
))
that's only show first line
#Compo has given a good answer. This is only to expound on it. Using aliases like GC should not be put into scripts. At the command line, sure, go ahead and reduce typing if you feel like it. Also, spelling out the parameter names provides more information and aids faster understanding.
To get only line 3.
GC .\mytext.txt -T 3|Select -L 1
Get-Content -Path '.\mytext.txt' -TotalCount 3 | Select-Object -Last 1
From the CMD console (Command prompt): (to get only line seven (7)
PowerShell "GC .\mytext.txt -T 7|Select -L 1"
PowerShell -NoProfile "Get-Content -Path '.\mytext.txt' -TotalCount 7 | Select-Object -Last 1"
To get lines 3 through 7:
$FirstLine = 3
$LastLine=7
powershell -NoProfile -Command "Get-Content -Path '.\t.txt' -TotalCount $LastLine | Select-Object -Last ($LastLine - $FirstLine + 1)"
Or, in a cmd.exe batch script.
SET "FIRSTLINE=3"
SET "LASTLINE=7"
powershell -NoProfile -Command ^
"Get-Content -Path '.\t.txt' -TotalCount %LASTLINE% |" ^
"Select-Object -Last (%LASTLINE% - %FIRSTLINE% + 1)"
#echo off
setlocal
set "FILE_TO_PROCESS=%~f1"
set /a LINE_NUMBER=%~2
set /a trim=LINE_NUMBER-1
break>"%temp%\empty"&&fc "%temp%\empty" "%FILE_TO_PROCESS%" /lb %LINE_NUMBER% /t |more +4 | findstr /B /E /V "*****"|more +%trim%
endlocal
try with this bat (called lineNumber.bat) the first argument is the file you want to process the second is the line number:
call lineNumber.bat someFile.txt 5
There are a couple of ways to do this. Your first option is to go through the for loop normally and break out of the loop once you reach the desired line.
#echo off
:: Specify which line to return
set get_line=7
:: Skip all lines before it, then print the next line and abort
set /a get_line-=1
for /F "skip=%get_line% delims=" %%A in (mytext.txt) do (
echo %%A
goto :end_loop
)
:end_loop
Your other option is to store all lines before the unwanted line in a temp variable and then display the next line.
#echo off
setlocal enabledelayedexpansion
:: Specify which line to return
set get_line=7
:: Skip all lines before it, then print the next line and abort
set /a get_line-=2
(
for /L %%A in (0,1,%get_line%) do set /p skip_line=
set /p return_line=
) <file.txt
echo !return_line!
Note that the first option is not suited for returning the first line of the script.
Since you said 'display', why not give PowerShell a shot:
From the PowerShell console:
GC .\mytext.txt -T 3|Select -L 1
From the CMD console (Command prompt):
PowerShell "GC .\mytext.txt -T 7|Select -L 1"
From a batch file:
#(PowerShell "GC .\mytext.txt -T 19|Select -L 1"&Pause)
Related
I don't know if its age or lack of practice. Either way I cannot wrap my head around this issue. I am trying to set a subroutine but the string that I am passing along are being split because of the space in string 3 and 4.
SET SubA=String1,String2,String 3,String 4
FOR %%A IN (%SubA%) DO MD "%%A"
I've tried parenthesis around the string
The <> brackets like Microsoft says to use. I have also tried this line below without success.
setlocal enableDelayedExpansion
For /F "tokens=* delims=" %%A IN (%Var%) DO MD "%%A"
Also I would love if possible could I make an list, possibly with an array. Like in Power shell I could do this. I really need to keep in the same batch file so the user could edit the list. I am aware that I could use caret but the easier I can make it for my client the better.
$Folders (
String1
String2
String 3
String 4
)
Edit: My desired result is to have this script create a set of folders like those pictured.
The simplest pure batch-file solution that doesn't require trickery is to use for's ability to enumerate space-separated tokens.
For this to work as intended, tokens that themselves contain spaces must be double-quoted:
#echo off & setlocal
:: Space-separated list of folder names, with names that contains
:: spaces themselves double-quoted.
SET SubA=String1 String2 "String 3" "String 4"
:: Loop over the list elements and create a directory for each.
FOR %%A IN (%SubA%) DO MD %%A
As Compo's helpful answer implies, you could actually pass this list to a single invocation of
MD: MD %SubA%
Unfortunately, as far as I know, batch files do not offer a convenient way to define lists in a one-item-per-line format.
However, you could provide the list of names via an external file, with each name on its own line (no double-quoting needed), which can then be parsed with for /f; e.g.:
#echo off & setlocal
:: Determine the full path of the file "names.txt"
:: located in the same folder as this batch file.
set "nameList=%~dp0names.txt"
:: Loop over all names in the file and call `md` with each.
for /f "usebackq delims=" %%n in ("%nameList%") do md "%%n"
And input file names.txt would then contain something like:
String1
String2
String 3
String 4
The simplest way to 'make' your directories is probably like this:
Set "SubA=String1,String2,String 3,String 4"
MD "%SubA:,=" "%" 2>NUL
As for working with the initial variable, and using it array like, you could do it like this:
#Echo Off & SetLocal EnableExtensions EnableDelayedExpansion
Set "SubA=String1,String2,String 3,String 4"
For /F "Delims==" %%G In ('"(Set Index[) 2>NUL"') Do Set "%%G="
Set "i=0"
Set "Index[!i!]=%SubA:,=" & Set /A i += 1 & Set "Index[!i!]=%"
(Set Index[) 2>NUL && Pause
Or you could do it like this:
#Echo Off & SetLocal EnableExtensions EnableDelayedExpansion
Set "SubA=String1,String2,String 3,String 4"
For /F "Delims==" %%G In ('"(Set Index[) 2>NUL"') Do Set "%%G="
Set "i=-1"
For %%G In ("%SubA:,=","%") Do (Set /A i += 1
Set "Index[!i!]=%%~G")
(Set Index[) 2>NUL && Pause
Here is another way to create the directories using the PowerShell that is already on your system if it is still supported by Microsoft. When you are satisfied that the correct directories will be created, remove the -WhatIf from the mkdir command.
SET "SubA=String1,String2,String 3,String 4"
powershell -NoLogo -NoProfile -Command ^
"'%SubA%'.split(',') | ForEach-Object { mkdir $_ -WhatIf | Out-Null }
A better way would be to test to see if the directory already exists before trying to create it.
SET "SubA=String1,String2,String 3,String 4"
powershell -NoLogo -NoProfile -Command ^
"'%SubA%'.split(',') | ForEach-Object {" ^
"if (-not (Test-Path -Path $_)) { mkdir $_ | Out-Null }" ^
"}"
i wanted to code a little update tool for a server.jar file to save me all the effort of doing it manually
the program i'm using creates a folder which contains a file when a new update is released. this is pretty much how the program works:
get hash of current server.jar
find latest created folder (eg. update12)
open the file in the update12 folder (eg. update12.txt)
***extract the hash code -> %newHash%*** thats where im having the issue
compare the extracted hashcode (%newHash%) and the calculated hashcode (%currentHash%)
if they are not equal go to www.downloadupdate.com/updates/%newHash%/server.jar
download the file and replace the old server.jar with the new one.
the issue i am having is that i cant read out the hash in the update12.txt the file is about 36000 symbols long and in one line only
"server": {"sha1": "16f18c21286a3f566d3d0431d13aa133bebe6eff"
i want to detect the "server": {"sha1": " part and copy the hash after that
i tried many options i found on this forum but none seemed to work
like this one
set /p txt=<update12.txt
pause >nul
echo %txt%
pause >nul
for /f %%i in ('powershell -noprofile -c "('%txt:"=\"%' -split '\""')[1]"') do set id=%%i
echo %id%
just caused the batch file to close instantly
furthermore set /p txt=
if you have any solution i would be grateful to hear it
#echo off
Setlocal EnableDelayedExpansion
xcopy %appdata%\.minecraft\versions\%MCversion%\%MCversion%.json %appdata%\.minecraft\versions\%MCversion%\%MCversion%.text*
ren %appdata%\.minecraft\versions\%MCversion%\%MCversion%.text %MCversion%.txt
set search1=
set search2=,
set search3=:
set textFile=%appdata%\.minecraft\versions\%MCversion%\%MCversion%.txt
:PowerShell
SET PSScript=%temp%\~tmpStrRplc.ps1
ECHO (Get-Content "%textFile%").replace("%search1%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
ECHO (Get-Content "%textFile%").replace("%search2%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
ECHO (Get-Content "%textFile%").replace("%search3%", "") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
SET PSScript=%temp%\~tmpStrRplc.ps1
echo done.
:skip
ECHO (Get-Content "%textFile%").replace("server", "`r`nlookup") ^| Set-Content "%textFile%">"%PSScript%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
echo done.
for /f %%a in ('findstr "lookup\"{\"sha1\"\"" %textFile%') do set "newVersion=%%a"
set newVersion=%newVersion:~15,40%
echo %newVersion%
del %textFile%
pause
:exit
exit
this code works for me, what it does:
copy the "update12.txt"
look for " " "," and ":" in the copied txt and delete the symbols
look for server replace it with a "*linebreak*lookup"
find the string lookup"{"sha1""
trim the edges of the string with 15,40
done.
I`m editing a bunch of files with mkvmerge and I'm doing this:
Video from original-001.mkv mux with audio from audio-001.mkv and add subtitle from sub-001.mkv.
I'm creating a bunch of .bat scripts and using notapad++ find and replace function to do this:
find 001 and replace for 002, save as 002.bat and move on.
Basically, there will always be a base file named 001.bat
What would be really great is this Notepad++ portion could be automated.
Find all strings "001", replace with "002", save as 002.bat
Find "002", replace with "003", save as 003.bat.
Up to 300.
And finally what I do is another script:
Call 001.bat
Call 002.bat and so on.
If I file doesn't exist there's no problem.
Is this possible using batch script on windows?
EDIT to add code as the way I'm going now:
Example of 001.bat
"C:/Program Files/MKVToolNix\mkvmerge.exe" --ui-language en --output ^"F:\original\original-001 ^(1^).mkv^" --language 0:eng --default-track 0:yes --language 1:eng --default-track 1:yes ^"^(^" ^"F:\original\original-001.mkv^" ^"^)^" --no-video --language 1:por ^"^(^" ^"F:\BR001.mp4^" ^"^)^" --track-order 0:0,0:1,1:1
And I have this (but it's powershell)
powershell -Command "(gc 001.bat) -replace '001', '002' | Out-File 002.bat"
powershell -Command "(gc 002.bat) -replace '002', '003' | Out-File 003.bat"
powershell -Command "(gc 003.bat) -replace '003', '004' | Out-File 004.bat"
powershell -Command "(gc 004.bat) -replace '004', '005' | Out-File 005.bat"
powershell -Command "(gc 005.bat) -replace '005', '006' | Out-File 006.bat"
and so on
Finally I use this:
call 001.bat
call 002.bat
call 003.bat
call 004.bat
call 005.bat
call 006.bat
and so on
But I did it all by hand, so a automated way would be amazing for all outputs of mkvtoolnix because I can use advanced renamer to change all episodes to 001, 002.. and such and filebot later to have the correct season and episode list.
I doubt, generating 300 nearly identical batchfiles is a good idea. Use just one and loop over your numbers:
#echo off
setlocal
for /l %%i in (1,1,300) do call :processFile %%i
goto :eof
:processFile
set "number=000%1"
set "number=%number:~-3%"
echo %number%: original-%number%.mkv audio-%number%.mkv sub-%number%.mkv
REM insert your mux command here
Here you go.
Go down to "** and does stuff to it ** RIGHT HERE **".
This is where you will search and replace on the new file.
#echo off
:: This is the meat of the whole script..
:: increment a number from 1 to 300
for /L %%n in (1,1,300) do call :check_copy_file %%n
goto :eof
:: lines here will never execute because goto :eof is like "return" to cmd.exe
:: ------------------------------------------------------
:: function -- check_copy_file
:: purpose -- takes an input number, increments it, pads it with zeros
:: -- copies original to new number name
:: -- ** and does stuff to it ** this is where you search and replace..
:: ------------------------------------------------------
:check_copy_file
Set existing_file_num=%1
Set /a new_file_num=%existing_file_num% +1
call :pad_with_zeros existing_file_num %existing_file_num%
call :pad_with_zeros new_file_num %new_file_num%
:: ** if there isn't a batch file to copy, return
if not exist %existing_file_num%.bat echo %existing_file_num%.bat doesn't exist!&& goto :eof
:: copy (for instance 001.bat to 002.bat)
copy %existing_file_num%.bat %new_file_num%.bat
:: ** and does stuff to it ** RIGHT HERE **
:: muck with the contents of %new_file_num%.bat
echo mucky mucking with file %new_file_num%.bat
goto :eof
:: ---------------------------------------
:: function -- pad_with_zeros
:: purpose -- adds up to two 0s as needed
:: ---------------------------------------
:pad_with_zeros
Set input_var=%1
Set input_val=%2
if "%input_val:~2,1%"=="" Set input_val=0%input_val%
if "%input_val:~2,1%"=="" Set input_val=0%input_val%
Set %input_var%=%input_val%
goto :eof
I found an answer to find all empty directories. I want to do the opposite to find and list non empty directories in a folder. The folders just go one level deep.
#echo off
for /d /r %1 %%A in (.) do (
dir /a /b "%%~fA" 2>nul | findstr "^" >nul || echo %%~fA
)
How to modify the above line to find non empty folders ?
In your particular situation, instead of using Dir you could use Where.exe, (Vista+), which has a handy /Q option, (enter Where /? at the Command Prompt for usage information).
From cmd.exe:
For /D %A In (*) Do #Where/Q "%A":*>Nul&&Echo %A
From a batch file:
#For /D %%A In (*) Do #Where/Q "%%A":*>Nul&&Echo %%A
Conversely with a small change you can report those without files:
From cmd.exe:
For /D %A In (*) Do #Where/Q "%A":*>Nul||Echo %A
From a batch file:
#For /D %%A In (*) Do #Where/Q "%%A":*>Nul||Echo %%A
In the above examples, if the string between the parentheses contains a path, e.g. MyFolder\*, "C:\Some Location\* or ..\RelPath\* you can optionally use Echo %~nxA / Echo %%~nxA if you prefer the output to be just the directory name.
Simply identify the directories with a non-zero Count. Using the -Directory switch will require PowerShell 3.0 or higher.
#ECHO OFF
powershell -NoProfile -Command ^
"(Get-ChildItem -Directory |" ^
"ForEach-Object { if ((Get-ChildItem $_).Count -ne 0) { $_.Name } })"
Usage:
C:>CALL get-nonemptydirs.bat
d2
junk
others
t t t
xxx
Here is a simple PowerShell script that will find all directories (within a directory) that have contents within them:
((Get-ChildItem -Directory -Path "C:\PATH-TO-FOLDER" | Where {$_.PSIsContainer -eq $True}) | Where {$_.GetFiles().Count -ne 0} | select FullName).FullName
If you want to write the results to a file, just append the following to the end:
| out-file -FilePath "C:\PATH-TO-OUTFILE\FILE.txt"
Full script:
((Get-ChildItem -Directory -Path "C:\PATH-TO-FOLDER" | Where {$_.PSIsContainer -eq $True}) | Where {$_.GetFiles().Count -ne 0} | select FullName).FullName | Out-File -FilePath "C:\PATH-TO-OUTFILE\FILE.txt"
I am using grep on windows to filter a file and would like to pipe the output to another batch script.
e.g.
grep "foo" bar.txt | mybatch.bat
and in mybatch i would like to process each matching line
e.g. mybatch.bat:
echo Line with foo: %1
on linux I can solve this via
grep "foo" bar.txt | while read x; do mybatch.sh $x; done
but no idea how I can do this on a windows machine.
Thanks in advance!
You can use for:
for /f %x in ('grep "foo" bar.txt') do call mybatch.cmd "%x"
This will call your batch file once for every non-empty line, just as your shell script example would do.
Here's the trick of the trade:
head.bat
#echo off
setlocal ENABLEDELAYEDEXPANSION
set n=%1
for /F "tokens=*" %%x in ('more') do (
echo %%x
set /A n -= 1
if !n! EQU 0 exit /b
)
Using it:
REM print the first 10 lines:
type test.txt | head 10