I need to use cmdlet but will only know what parameter to use at runtime.
for ex, I may need to call
Get-ChildItem -filter <string>
or
Get-childItem -exclude <string>
or
Get-childItem -recurse
etc.
but I will know only at runtime which of -filter or -exclude or -recurse or a combination of them be needed.
[ Get-ChildItem is only an example to illustrate the need not the real thing ]
is it possible to do this except by using a huge if-then-else structure ? is it possible to use a cmdlet selecting parameters at runtime ?
TIA, Peyre.
using you example you can do it something like this:
Function test ($value , [switch]$paramA, [switch]$paramB)
{
if ($paramA)
{
$cmd = "-filter $value"
}
if($paramB)
{
$cmd = "-exclude $value"
}
iex "dir $cmd"
}
to test it try it like this:
test -value *.ps1 -paramA
or
test -value *.ps1 -paramB
Related
I am currently learning LPTHW Ex 46. In his video tutorial, Zed had done the following commands:
Find NAME within files using grep -r "NAME" *.
Find all files with extension ending in .pyc using find . -name "*pyc" -print.
Unfortunately, the above code does not work on Windows PowerShell. May I know what their Windows PowerShell equivalents are?
Based on my search, item 1 can be replaced by Select-String. However, it is not as good as we can only search specific files and not directories. For example, while this would work:
Select-String C:\Users\KMF\Exercises\Projects\gesso\gesso\acrylic.py -pattern "NAME"
this would not:
Select-String C:\Users\KMF\Exercises\Projects\gesso -Pattern "NAME"
and it gives the following error
Select-String : The file C:\Users\KMF\Exercises\Projects\gesso can not be read: Access to the path 'C:\Users\KMF\Exercises\Projects\gesso' is denied.
For item 2 I could not find a similar function.
grep and find are Unix/Linux shell commands. They won't work in PowerShell unless you install a Windows port of them.
As you already found out, Select-String is the PowerShell equivalent for grep. It doesn't recurse by itself, though, so you have to combine it with Get-ChildItem to emulate grep -r:
Get-ChildItem -Recurse | Select-String -Pattern 'NAME'
For emulating find you'd combine Get-ChildItem with a Where-Object filter:
Get-ChildItem -Recurse | Where-Object { $_.Extension -eq '.pyc' }
PowerShell cmdlets can be aliased to help administrators avoid extensive typing (since PowerShell statements tend to be rather verbose). There are several built-in aliases, e.g. ls or dir for Get-ChildItem, and ? or where for Where-Object. You can also define aliases of your own, e.g. New-Alias -Name grep -Value Select-String. Parameter names can be shortened as long as the truncated parameter name remains unique for the cmdlet. When cmdlets allow positional parameters they can even be omitted entirely.
With all of the above your two PowerShell statements can be reduced to the following:
ls -r | grep 'NAME'
ls -r | ? { $_.Extension -eq '.pyc' }
Note however, that aliases and abbreviations are mainly intended as an enhancement for console use. For PowerShell scripts you should always use the full form, not only for readability, but also because aliases may differ from environment to environment. You don't want your scripts to break just because they're run by someone else.
I am new to PowerShell.
I wanted to write a simple program to list all *.bak files which I can then either sort by date or size as shown below.
$Drives = Get-WMIObject -class win32_logicaldisk -filter "DriveType = 3" ;
foreach ($d in $Drives){
If (($d.deviceId -ne "C:") -and ($d.VolumeName -ne "PAGEFILE")) {
$backups += Get-ChildItem -Path $d.deviceID -Recurse -filter *.bak
}
This generally works fine except when say for example D: drive has only one *.bak file.
In that case I get an error.
Method invocation failed because [System.IO.FileInfo] doesn't contain a method named 'op_Addition'.
At F:\work\PowerShell\DiskSpace\generate-disk-report-v2.ps1:39 char:13
+ $backups += <<<< Get-ChildItem -Path $d.deviceID -Recurse -filter *.bak
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
If I add an additional junk.bak to that drive, it works fine.
In my case, I found that the variable needs to be initialized as an array and Get-ChildItem needs to be returned as an array even, or especially, if it's only returning one file.
In your case:
$backups = #() - (Before calling Get-ChildItem)
and
$backups = #(Get-ChildItem -Path $d.deviceID -Recurse -filter *.bak) - (Cast as an array)
I'm trying to write a very simple PowerShell script to give me the total number of items (both files and folders) in a given folder (c:\MyFolder). Here's what I've done:
Write-Host ( Get-ChildItem c:\MyFolder ).Count;
The problem is, that if I have 1 or 0 items, the command does not work---it returns nothing.
Any ideas?
You should use Measure-Object to count things. In this case it would look like:
Write-Host ( Get-ChildItem c:\MyFolder | Measure-Object ).Count;
or if that's too long
Write-Host ( dir c:\MyFolder | measure).Count;
and in PowerShell 4.0 use the measure alias instead of mo
Write-Host (dir c:\MyFolder | measure).Count;
I finally found this link:
https://blogs.perficient.com/microsoft/2011/06/powershell-count-property-returns-nothing/
Well, it turns out that this is a quirk caused precisely because there
was only one file in the directory. Some searching revealed that in
this case, PowerShell returns a scalar object instead of an array.
This object doesn’t have a count property, so there isn’t anything to
retrieve.
The solution -- force PowerShell to return an array with the # symbol:
Write-Host #( Get-ChildItem c:\MyFolder ).Count;
If you need to speed up the process (for example counting 30k or more files) then I would go with something like this..
$filepath = "c:\MyFolder"
$filetype = "*.txt"
$file_count = [System.IO.Directory]::GetFiles("$filepath", "$filetype").Count
Only Files
Get-ChildItem D:\ -Recurse -File | Measure-Object | %{$_.Count}
Only Folders
Get-ChildItem D:\ -Recurse -Directory | Measure-Object | %{$_.Count}
Both
Get-ChildItem D:\ -Recurse | Measure-Object | %{$_.Count}
You can also use an alias
(ls).Count
Recursively count files in directories in PowerShell 2.0
ls -rec | ? {$_.mode -match 'd'} | select FullName, #{N='Count';E={(ls $_.FullName | measure).Count}}
In powershell you can to use severals commands, for looking for this commands digit: Get-Alias;
So the cammands the can to use are:
write-host (ls MydirectoryName).Count
or
write-host (dir MydirectoryName).Count
or
write-host (Get-ChildrenItem MydirectoryName).Count
To count the number of a specific filetype in a folder.
The example is to count mp3 files on F: drive.
( Get-ChildItme F: -Filter *.mp3 - Recurse | measure ).Count
Tested in 6.2.3, but should work >4.
I have a directory on a share were the prefix of each file name has to be moved to a specific directory. The -filter commands works to move the files but it would be nice to use the value of an array instead. Any help would be greatly appreciated.
$source ="\\127.0.0.1\share\"
$File_Array_8HP70=#("108701")
$File_Array_8HP70X=#("108702")
$File_Array_9HP48=#("109401", "1094080", "1094090")
$File_Array_9HP48X=#("109402", "1094091", "1094082", "1094092")
$destination="\\127.0.0.1\TestFolder1\$DTS"
$destination1="\\127.0.0.1\TestFolder2\$DTS"
$destination2="\\127.0.0.1\TestFolde3\$DTS"
$destination_array=#("$destination", "$destination1", "$destination2")
# filter works below - need to use array
#$files = get-childitem $source -filter "108701*" -recurse
#foreach ($file in $files)
#{move-item $file.fullname $destination_array[0] -force}
$files = gci $source |select-object -equals $file_array_8HP70
foreach ($file in $files)
{move-item $file.name is $($file_array_8hp70.name) $destination_array[0] -force}
If you write :
$source ="\\127.0.0.1\share\*"
$File_Array_8HP70_start = $File_Array_8HP70 | % {$_+"*"}
$files = get-childitem $source -include $File_Array_8HP70_start -recurse
It should help.
I'm not so hot with PowerShell yet, but have managed to get this command to work quite nicely:
get-childitem "C:\Code\WC1" -Recurse | select-string "insert into\s+my_table"
Thing is, I know I'm going to struggle to remember this, so how can I make it into a function where the path supplied to get-childitem and the search regex are parameters?
I'm using PowerShell 2.0.
more commonly these days the parameters are being called after the function declaration e.g.
Function Find-Code {
param([string] $path, [string] $pattern)
get-childitem $path -Recurse | select-string $pattern
}
Function Find-Code([string] $path, [string] $pattern)
{
get-childitem $path -Recurse | select-string $pattern
}
You can put this in your PowerShell Profile.
An easy way to do this is to edit the $profile file (run something like notepad $profile from your PowerShell prompt) and just paste the text right in.