So I am running the following shellscript and I receive the error syntax error near unexpected token 'done'. What is wrong with it ? What have I missed ?
#!/bin/sh
df -H | grep -vE '^Filesystem|tmpf|cdrom' | awk ' {print $5 " " $6}' | while read output
do
echo $output
usep=$(echo $output | awk '{print $1}' | cut -d'%' -f1)
echo $usep
partition=$(echo $output | awk '{print $2}' )
if [ $usep -ge 90 ]; then
echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date) : $usep%" |
mail -s "Alert: Critical Almost out of disk space $partition $usep%"
user#mail.eu
fi
if [ $usep -ge 5 ]; then
echo "Running out of space \"$partition ($usep%)\" on $(hostname) as on $(date) : $usep%" |
mail -s "Alert: Warning Almost out of disk space $partition $usep%" user#mail.eu
fi
done
I copy-pasted your script and tested it under Cygwin.
I get the syntax error using Windows end-of-line (CRLF) but the script works fine if converted to Unix EOL (LF)
Related
The original code was this:
curl -sL https://ftp.apnic.net/stats/apnic/delegated-apnic-latest | \
grep "apnic|JP|ipv4" | \
awk -F '|' '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' | \
tee JP_IPv4.txt
I wanted to convert it to PowerShell, this is how far I got:
Invoke-WebRequest -Uri "https://ftp.apnic.net/stats/apnic/delegated-apnic-latest" |
Select-String -Pattern "afrinic\|ZA\|ipv6" -ca | Select-Object -exp line |
I need to figure out how to convert the last part that uses awk command to PowerShell.
I use PowerShell 7.3
The awk script appears to calculate the subnet prefix length from the network size.
You can replace the awk log(...) function call with [Math]::Log(...) in PowerShell to perform the exact same calculation:
# this takes care of the `curl` part
Invoke-WebRequest -Uri "https://ftp.apnic.net/stats/apnic/delegated-apnic-latest" -OutFile delegated_networks.txt
# this takes care of the `grep` part
Get-Content delegated_networks.txt |Where-Object {$_ -like 'apnic|JP|ipv4|*'}
# this emulates the `awk | tee` part
$data|ForEach-Object {
# -F '|'
$cells = $_.Split('|')
# '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }'
'{0}/{1}' -f $cells[3],(32 - [Math]::Log($cells[4])/[Math]::Log(2))
} |Tee-Object -FilePath JP_ipv4.txt
As #mklement0 kindly points out, you can also combine the log-conversion operation into a single call in PowerShell:
PS ~>[Math]::Log(4096)/[Math]::Log(2)
12
PS ~>[Math]::Log(4096, 2)
12
I need to search for a term in a file and display an index in the search results so that referencing is easy.
The command in bash would be:
cat <file> | grep 'Table: ' | cat -n
What I have so far in Powershell:
Get-Content <file> | Select-String 'Table: ' | Select-Object -Property LineNumber, Line
Unfortunately, I didn't realize that LineNumber gives the actual line in the file and not the index in the results list.
How can I translate the bash command into its Powershell equivalent?
Indeed, the .Line property of the objects output by Select-Object indicates the line number of each match in a given input file.
PowerShell has no direct equivalent of cat -n (prepending a 1-based index to all input lines on output), but it's not hard to roll your own using the ForEach-Object cmdlet:
$i = 0
Get-Content file.txt | Select-String 'Table: ' | ForEach-Object {
"{0,6}`t{1}" -f ++$i, $_.Line
}
The above uses -f, the format operator, to left-space-pad to 6 characters (,6) the first RHS operand ({0}), which is the (incremented) index, ++$i, followed by a tab character (`t) and the second RHS operand ({1}), which is the input line at hand ($_.Line).
Just use WSL:
bash -c "cat <file> | grep 'Table: ' | cat -n"
This will run the bash code in powershell. For a true powershell option you could do this:
foreach ($line in $(Get-Content -Path <filepath> | Select-String 'Table: ')){
$count++
echo "$count $line"
}
I'm using the following PowerShell command:
dir -r -include *.log | Select-String "Some pattern" | Out-File .\findings.out
If I open the findings.out file the "redirected" loglines include additional line breaks, that were not included in the original logfiles, e.g.:
Original logline:
xxxx.log:3977:2016-05-03T07:39:13.847+02:00; INFO ; hello world
Logline findings.out:
xxx.log:3977:2016-05-03T07:
39:13.847+02:00; INFO ;
hello world
Any hints?
Please consider the following:
$File = "$env:TEMP\test.txt"
All content on one line because the whole string is now quoted between ''' single quotes (or double quotes '"'):
'xxx.log:3977:2016-05-03T07:39:13.847+02:00; INFO ; hello world' | Out-File $File
Only 'hello world' is in the file:
'xxx.log:3977:2016-05-03T07:39:13.847+02:00'; 'INFO'; 'hello world' | Out-File $File
Because PowerShell sees the following:
Write-Output 'xxx.log:3977:2016-05-03T07:39:13.847+02:00'
Write-Output 'INFO'
Write-Output 'hello world' | Out-File $File
As you can see, only the last line is written to the CmdLet Out-File.
The last two statements are the same. The semicolon ';' is a PowerShell code seperator. So it's the same if you write it on multiple lines without the semicolon or on one line with semicolons between the strings
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 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