I'm trying to create an index of machine names to loop through. The file looks right but fails to loop through machines at all as if there is hidden characters or something about the file that is unusual. What am I missing? Thanks - yeah I'm a newbie.
PowerShell:
$uncServer="\\*******\DHCP"
$username="*****"
$password="*******"
net use $uncServer $password /USER:$username
$input_path=$uncServer+"\"+'winsexport.txt'
$output_file='D:\Projects\StoreControls\machinfo\allworkstations.txt'
$regex='\b[S]\d{6}\b'
Select-String -Path $input_path -Pattern "ACTIVE" |Select-Object Line | `
Select-String -Pattern $regex -Allmatches|%{$_.Matches}|%{$_.Value}| get-unique > $output_file
net use $uncServer /delete
eg. output
s123420
s123421
.
.
loop logic:
FOR /F %%i IN (d:***********\allworkstations.txt) DO ( #this does nothing
start /B d:\***********\GetMachInfo.bat %%i
PING 1.1.1.1 -n 1 -w 1000 >NUL
)
PING 1.1.1.1 -n 1 -w 1000 >NUL
exit
It is hard to speculate what knowing what's inside winsexport.txt file. The most likely culprit is CR or LF character so try and remove these. Change
... -Allmatches|%{$_.Matches}|%{$_.Value}| get-unique ...
to
... -Allmatches|%{$_.Matches}|%{$_.Value -replace "`r|`n|\s|`t",""}| get-unique ...
Why do you switch back to command prompt loop? You could carry on in powershell
foreach($machine in (gc d:***********\allworkstations.txt)){
d:\***********\GetMachInfo.bat $machine
sleep 1
}
sleep 1
Related
I have a 3 txt files namely file1 , file2 , file3 containing data separated with "|"
I need to filter all the lines that only having "1" in columnx and print the value in the column "account"
file1.txt
line|account|column3|columnx
line1|111111|jahadkadaldabndal|1
line2|2323413341|adajkadadbjkqqweq|0
line3|21122|adaieaqelqq|0
line4|236521|jadad|1
file2.txt
line|account|column3|columnx
line1|1117831|jahadkadaldabndal|1
line2|23234178841|adajkadadbjkqqweq|1
line3|21122|adaieaqelqq|0
line4|236526|jadad|1
file3.txt
line|account|column3|columnx
line1|1113333|jahadkadaldabndal|1
line2|232341335|adajkadadbjkqqweq|1
line3|21124|adaieaqelqq|1
line4|236523|jadad|1
output should be like this :
111111
236521
1113333
236523
21124
232341335
1117831
23234178841
236526
i have a code but online for one file txt only.
powershell -nop -c "(import-csv .\*.txt -del '|'|? columnx -eq 1).account"
I'm still figuring out what I should use I'm really new in this stuff can anyone teach me or give me some code so that I can finish this one thank you.
Well you were nearly there with your powershell command, you just needed an foreach-loop.
This here prints out any account value where columnx is 1:
Get-ChildItem -Filter "*.txt" | % {Import-Csv $_.Fullname -Delimiter '|'} | Where-Object {$_.columnx -eq 1} | Select-Object -ExpandProperty account
Note that % is just an alias for foreach and $_ equals each object of the loop, so every .csv given to it.
To follow up on your questions from the comment:
What if my txt file has no header?
Import-Csv has a -Header option which lets you add Headers for the Import, in your case it should look like this:
Get-ChildItem -Filter "*.txt" | % {Import-Csv $_.Fullname -Delimiter '|' -Header "line","account","column3","columnx"} | Where-Object {$_.columnx -eq 1} | Select-Object -ExpandProperty account
What if I need the last two column to have the value "1"
You can add additional checks to the Where-Object using -and like this:
Get-ChildItem -Filter "*.txt" | % {Import-Csv $_.Fullname -Delimiter '|'} | Where-Object {$_.columnx -eq 1 -and $_.column3 -eq 1} | Select-Object -ExpandProperty account
#echo off
for %%A in (*.txt) do for /F "usebackq skip=1 tokens=2,4 delims=|" %%A in ("%%~A") do (
for %%B in (%%B) do if %%B EQU 1 echo %%A
)
pause
for %%A in (*.txt) iterates through each text file. the wildcard can be set as appropriate e.g. file*.txt or whatever as appropriate to your case.
for /F "usebackq skip=1 tokens=2,4 delims=|" reads each file that is passed by the parent FOR, process each file line by line takes tokens 2 and 4 from each line (that is account and columnx). skip=1 skips the first line if the file contains the header line|account|column3|columnx if not remove skip=1
for %%B in (%%B) is to remove any leading/trailing spaces from the last token (columnx) for comparison against 1 to be correct if last the column contains spaces.
as you also gave the batch-file tag:
#echo off
for /f "tokens=2 delims=|" %%a in ('type file*.txt 2^>nul ^|findstr /e "|1"') do (
echo %%a|findstr /x "[0-9][0-9]*"
)
get the second token from each line that ends with |1 and filter it for "numbers only"
I'm trying to output a numeral value from a ffmpeg output and add it to a text file.
I'd like to run it as a single line from a batch file where I have all my variables set up already, but I'm not sure if it's even possible.
This is the output string, from where i want to copy the average value:
[Parsed_psnr_0 # 0000000003763ec0] PSNR y:18.250891 u:33.358190 v:36.566447 average:19.962586 min:11.944585 max:41.255356
In this case 19.962586, i got several 100 files to process and the number is always different.
Here is a weak attempt out of ignorance to do that:
powershell Get-Content -Path "'D:\work folder\test.txt'" | -match 'average:(.+?) min:' | Out-File -Path "D:\work folder\test_result.txt"
not working and neither did the 100 variations I tried, but I've included it as a rough idea of what I am trying.
Test string:
[Parsed_psnr_0 # 0000000003763ec0] PSNR y:18.250891 u:33.358190 v:36.566447 average:19.962586 min:11.944585 max:41.255356
PowerShell solution (can toss into a .cmd file):
powershell -Command "(Get-Content -Path 'D:\workfolder\test.txt') -match 'average:(.+?)' | Out-File -FilePath 'D:\workfolder\test_result.txt' -Append"
Update:
SET "PS=%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe"
%PS% -Command "gc 'D:\workfolder\test.txt'|%{If($_-match 'average:(.+?)'){$Matches[0]}}|Out-File -FilePath 'D:\workfolder\test_result.txt' -Append"
Here are two possible ways you can do this with a batch file. There are other solutions as well. But either of these should work based on your example.
#echo off
REM Option 1
FOR /F "tokens=5 delims=:" %%G IN (test.txt) DO (
FOR /F "tokens=1" %%H IN ("%%~G") DO set "average1=%%~H"
)
echo average1: %average1%
REM option 2
setlocal enabledelayedexpansion
FOR /F "delims=" %%G IN (test.txt) DO (
set "line=%%~G"
FOR /F "tokens=1" %%H IN ("!line:*average:=!") DO set average2=%%H
)
endlocal&set "average2=%average2%"
echo average2: %average2%
pause
the following is a working powershell solution:
powershell -Command "(Get-Content -Path 'C:\file.txt').Split(' ') | foreach { if ($_ -match 'average'){ $_ -replace """[^^.0-9]""" , '' | Out-File -FilePath 'D:\file_output.txt' -Append}}"
credit goes to Adrian C.
i'm trying to delete the "unwanted" class lines from an HTML file using power shell script
<a class="unwanted" href="http://www.mywebsite.com/rest/of/url1" target="_blank">my_file_name1</a><br>
<a class="mylink" href="http://www.mywebsite.com/rest/of/url2" target="_blank">my_file_name2</a><br>
<a class="unwanted" href="http://www.mywebsite.com/rest/of/url3" target="_blank">my_file_name3</a><br>
Currently i'm replacing strings using this script
$s = "old string"
$r = "new string"
Get-ChildItem "C:\Users\User\Desktop\Folder" -Recurse -Filter *.html | % {
(Get-Content $_.FullName) `
| % { $_ -replace [regex]::Escape($s), $r } `
| Set-Content $_.FullName
}
Since you tagged your question also with cmd and batch-file, I want to contribute a related answer.
cmd.exe/batch scripting does not understand HTML file format, but if your HTML file(s) look(s) like the sample data you provided (the <a> tag and the corresponding </a> tag are in a single line, and there is nothing else (than <br>)), the following command line could work for you -- supposing a HTML file to process is called classes.html and the modified data is to be written to file classes_new.html:
> "classes_new.html" findstr /V /I /L /C:"class=\"unwanted\"" "classes.html"
This only works if the string class="unwanted" occurs only in the <a> tags that need to be removed.
To process multiple files, the following batch script could be used, based on the above command line:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ARGS=%*"
setlocal EnableDelayedExpansion
for %%H in (!ARGS!) do (
endlocal
call :SUB "%%~H"
setlocal
)
endlocal
endlocal
exit /B
:SUB file
if /I not "%~x1"==".html" if /I not "%~x1"==".htm" exit /B 1
findstr /V /I /L /C:"class=\"unwanted\"" "%~f1" | (> "%~f1" find /V "")
exit /B
The actual removal of lines is done in the sub-routine :SUB, unless then file name extension is something other than .html or htm. The main script loops through all the given command line arguments and calls :SUB for every single file. Note that this script does not create new files for the modified HTML contents, it overwrites the given HTML files.
Removing lines is even easier than replacing them. When outputting to Set-Content, simply omit the lines that you want removed. You can do this with Where-Object in place of your Foreach.
Adapting your example:
$s = "unwanted regex"
Get-ChildItem "C:\Users\User\Desktop\Folder" -Recurse -Filter *.html | % {
(Get-Content $_.FullName) `
| where { $_ -notmatch $s } `
| Set-Content $_.FullName
}
If you want literal matching instead of regex, substitute the where clause
where { -not $_.Contains($s) } `
Note this is using the .NET function [String]::Contains(), and not the PowerShell operator -contains, as the latter doesn't work on strings.
Try using multiline strings for your $s and $r. I tested with the HTML examples you posted as well and that worked fine.
$s = #"
old string
"#
$r = #"
new string
"#
Get-ChildItem "C:\Users\User\Desktop\Folder" -Recurse -Filter *.html | % {
(Get-Content $_.FullName) `
| % { $_ -replace $s, $r } `
| Set-Content $_.FullName
}
We have the following unix command:
/usr/bin/tail -n 1 %{path} | grep --silent -F "%{message}" && rm -f %{path}%
This:
/usr/bin/tail -n 1 %{path} gets the last line in the file that the path variable refers to
| grep --silent -F "%{message}" pipes the output to another command, grep, which checks if the output of the previous command is equal to the value of message
&& rm -f %{path}% if the values are equal, then delete the file refered to by path
The above line is in a configuration file which is allows for calls to be made to the underlying operating system.
I want to replicate the functionalirty on windows.
I tried this:
command => 'powershell -Command "& {Get-Item $args[0] | ? { (Get-Content $_ -Tail 1).Contains($args[1]) }| Remove-Item -Force}" "'%path%'" "'%message%'"'
This error is thrown:
Error: Expected one of #, {, } at line 15, column 131 (byte 498)
Line 15 is the line in the configuration file which contains the above.
Thanks
PowerShell solution:
$path = 'C:\path\to\your.txt'
$message = 'message'
Get-Item $path | ? { (Get-Content $_ -Tail 1).Contains($message) } | Remove-Item -Force
If you want to run it from a command line, call it like this:
powershell -Command "& {Get-Item $args[0] | ? { (Get-Content $_ -Tail 1).Contains($args[1]) } | Remove-Item -Force}" "'C:\path\to\your.txt'" "'message'"
You can use tailhead.bat (pure batch script utility) that can be used to show lasts/fists lines of a file.Instead of Grep you can use findstr or find :
tailhead.bat tailhead -file=%pathToFile% -begin=-3|find "%message%"
I'm looking for the PowerShell equivalent to grep --file=filename. If you don't know grep, filename is a text file where each line has a regular expression pattern you want to match.
Maybe I'm missing something obvious, but Select-String doesn't seem to have this option.
The -Pattern parameter in Select-String supports an array of patterns. So the one you're looking for is:
Get-Content .\doc.txt | Select-String -Pattern (Get-Content .\regex.txt)
This searches through the textfile doc.txt by using every regex(one per line) in regex.txt
PS) new-alias grep findstr
PS) C:\WINDOWS> ls | grep -I -N exe
105:-a--- 2006-11-02 13:34 49680 twunk_16.exe
106:-a--- 2006-11-02 13:34 31232 twunk_32.exe
109:-a--- 2006-09-18 23:43 256192 winhelp.exe
110:-a--- 2006-11-02 10:45 9216 winhlp32.exe
PS) grep /?
I'm not familiar with grep but with Select-String you can do:
Get-ChildItem filename.txt | Select-String -Pattern <regexPattern>
You can also do that with Get-Content:
(Get-Content filename.txt) -match 'pattern'
I had the same issue trying to find text in files with powershell. I used the following - to stay as close to the Linux environment as possible.
Hopefully this helps somebody:
PowerShell:
PS) new-alias grep findstr
PS) ls -r *.txt | cat | grep "some random string"
Explanation:
ls - lists all files
-r - recursively (in all files and folders and subfolders)
*.txt - only .txt files
| - pipe the (ls) results to next command (cat)
cat - show contents of files comming from (ls)
| - pipe the (cat) results to next command (grep)
grep - search contents from (cat) for "some random string" (alias to findstr)
Yes, this works as well:
PS) ls -r *.txt | cat | findstr "some random string"
So I found a pretty good answer at this link:
https://www.thomasmaurer.ch/2011/03/powershell-search-for-string-or-grep-for-powershell/
But essentially it is:
Select-String -Path "C:\file\Path\*.txt" -Pattern "^Enter REGEX Here$"
This gives a directory file search (*or you can just specify a file) and a file-content search all in one line of PowerShell, very similar to grep. The output will be similar to:
doc.txt:31: Enter REGEX Here
HelloWorld.txt:13: Enter REGEX Here
I find out a possible method by "filter" and "alias" of PowerShell, when you want use grep in pipeline output(grep file should be similar):
first define a filter:
filter Filter-Object ([string]$pattern) {
Out-String -InputObject $_ -Stream | Select-String -Pattern "$pattern"
}
then define the alias:
New-Alias -Name grep -Value Filter-Object
final, put the former filter and alias in your profile:
$Home[My ]Documents\PowerShell\Microsoft.PowerShell_profile.ps1
Restart your PS, so you can use it:
alias | grep 'grep'
References
alias:
Set-Alias here
New-Alias here
Filter (Special function) here
Profiles (just like .bashrc for bash): here
out-string (this is the key) here:
in PowerShell Output is object-based hereļ¼so the key
is to convert object to string and grep the string.
Select-String here:
Finds text in strings and files
This question already has an answer, but I just want to add that in Windows there is Windows Subsystem for Linux WSL.
So for example if you want to check if you have service named Elasicsearch that is in status running you can do something like the snippet below in powershell
net start | grep Elasticsearch
but select-String doesn't seem to have this option.
Correct. PowerShell is not a clone of *nix shells' toolset.
However it is not hard to build something like it yourself:
$regexes = Get-Content RegexFile.txt |
Foreach-Object { new-object System.Text.RegularExpressions.Regex $_ }
$fileList | Get-Content | Where-Object {
foreach ($r in $regexes) {
if ($r.IsMatch($_)) {
$true
break
}
}
$false
}
Maybe?
[regex]$regex = (get-content <regex file> |
foreach {
'(?:{0})' -f $_
}) -join '|'
Get-Content <filespec> -ReadCount 10000 |
foreach {
if ($_ -match $regex)
{
$true
break
}
}