I'm trying to determine whether the directories under a specified root directory contain files that match a certain pattern, in my case RT*.dcm.
I'm using Powershell 2.0 and I first obtain all sub-directories beneath the specified root directory using
$dirList = Get-ChildItem $homeDir -recurse | where {$_.Attributes -eq 'Directory'} | Select-Object FullName
I then loop through these to see if they contain *.dcm files using (perhaps there's a better way?)
# Find files with a "dcm" extension.
$fileList = Get-ChildItem $dir.fullname | where {$_.extension -eq ".dcm"} | Select-Object FullName
# Look for directories that contain *.dcm files
if ($fileList.Count -gt 0) {
[Console]::WriteLine("Dicom directory: " + $dir.fullname)
$dicomDirList += $dir
}
The above two sections work ok
I then search through the found directories using
foreach($dir in $dicomDirList) {
$rtFileList = Get-ChildItem $dir | where {$_.name -like "RT*.dcm"} | Select-Object FullName
foreach($file in $rtFileList) {
[Console]::WriteLine("RT likey file: " + $file.fullname)
}
}
However this doesn't find the files I know that are there?
If I use
Get-ChildItem C:\myfolder\RT*.dcm
this works, but I can't figure out how to use the returned items from the previous Get-ChildItem call
Could someone please point me in the right direction?
It looks like you may be over-complicating things.
To accomplish what Get-ChildItem C:\myfolder\RT*.dcm does for the entirety of $homeDir (which is what I believe you're trying to do), you can use a single Get-ChildItem command:
Get-ChildItem $homeDir -Recurse | Where-Object{$_.Name -like "RT*.dcm"}
This searches the entirety of $homeDir recursively for all of the .dcm files you're looking for and returns them.
Related
I am trying to enumerate a list of servers from Active Directory, and then insert the server name into a UNC path as part of a copy command.
When I execute the script, I get the result below. I think that maybe I have to convert my variable, but I am not sure what to convert it to.
VERBOSE: Performing the operation "Copy File" on target "Item: C:\davidtemp\Logo.png Destination: \#{name=NCIDITSTWEB07}\c$\program files...
$webdev = Get-ADOrganizationalUnit -filter {name -like "*dev*"} | where {$_.DistinguishedName -like "*relativity*"}
$ServerList = Get-ADComputer -SearchBase $webdev | where {$_.name -like "*web*"} | select name | sort name
Foreach($server in $ServerList)
{
$scriptBlockwork = { copy C:\davidtemp\Logo.png "\\$server\c$\program files\web\images" -Force -Verbose}
Invoke-Command -ScriptBlock $scriptBlockwork -verbose
}
I reached out to a friend who was able to help. I was not defining the variable properly.
I needed to use -expandProperty to get the results into a format that worked with the pipeline
$ServerList = Get-ADComputer -SearchBase $webdev | where {$_.name -like "web"} | select -expandProperty name
Hopefully this helps someone else who might be having a similar issue.
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 trying to copy 7 random .txt files to a different location, but sub-folders get copied instead of the .txt files.
Here is my script:
$d = #(gci G:\Users\Public\Test) | resolve-path | get-random -count 2
$d | gci | get-random -count 7
Copy-Item $d -destination G:\Users\Public\Videos
What do I need to change?
One possible solution might be to use the PSIsContainer attribute to filter out folders.
I tried the following...
$d = gci "C:\Work\a\*.txt" | Where {$_.psIsContainer -eq $false}| resolve-path | get-random -count 7
Copy-Item $d -destination C:\Work\b
The where clause filtered out anything that was not a "container" and ignored the test folders I had set up. If you need .txt files specifically then use the wildcard included in the path as above.
Also, if you were to add -recurse then it would presumably search in all sub folders of your original search location and still filter out any "folders" for copying. Though I haven't tested this very thoroughly.
$d = gci "C:\Work\a\*.txt" -recurse | Where {$_.psIsContainer -eq $false}| resolve-path | get-random -count 7
I'm trying to select all files of a certain type in a given directory EXCEPT ones beginning with certain names. Why didn't this code work?
PS C:\Documents and Settings\wdennis> Get-Item -Path ($AppDir + "reports\*.dbf") | Where-Object {$_.Name -ne "reports*" -or "category*"}
Directory: C:\Program Files\Application\reports
Mode LastWriteTime Length Name
---- ------------- ------ ----
----- 1/4/2007 9:37 AM 4842 category.dbf
----- 9/7/2007 1:53 PM 43903 reports.dbf
I'm pretty new to PS, and very tired to boot, so maybe that's why I'm not understanding why this didn't work. How to do this?
I think that -eq and -ne match the given string and don't support wildcards.
Only -like supports wildcards for pattern matching.
You can however use a regular expression with the -notmatch switch to achieve what you want. Since it's a regular expression now you need to use .* instead of *. And the beginning is marked with ^.
So you end with this
{$_.Name -notmatch "^reports.*|^category.*"}
The whole command
Get-Item -Path ($AppDir + "reports\*.dbf") | Where-Object {$_.Name -notmatch "^reports.*|^category.*"}
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.