What is the equivalent of »dir /s /b *foo*.docx« in powershell - powershell

I am looking for the powershell equivalent for cmd.exe's
dir /s /b *foo*.docx
I'd like to create an alias (or scriptlet?) for this.
I have found How do I do 'dir /s /b' in PowerShell? but with this approach I seem unable to pass the argument *foo*.docx.

As stated in my comment above, you're looking for:
gci -recurse -filter *foo*.docx | select -expandproperty fullname
gci or Get-ChildItem will return a list of file system objects that match the filter you specified. Each object will have a whole load of information attached with it, but as you're only interested in the path, you can just take the fullname property by piping to select as shown. The -expandproperty flag will ensure the result is returned as a string array rather than a list of objects.

Get-ChildItem -Recurse -Filter *foo*.docx | Select-Object FullName | Sort-Object Length

Related

Get-ChildItem with filter returns files that match but includes some that dont

Get-ChildItem -Path "my-path" -Filter "ABGH14__*"
When I run this I get several files that start with the string "ABGH14__" but also a few that obviously DO NOT start with that string in their file name.
What can I check?
If I change to use Where-Object
I get list with no extraneous names included.
Why not the first example?
Get-ChildItem -Path "my-path" | Where-Object {$_.Name -like 'ABGH14__*}
Unfortunately, -filter can match the short file name versions.
cmd /c dir /x my-path\ABGH14__* # show short filenames
get-childitem -filter *~1* # would match a lot of short filenames

Create text file containing a list of all files of a certain type with their filesize

I want to create a text file with all filenames of a certain filetype plus the filesize, recursively from a specified directory and all subdirectories.
For example: Listing all .jpg files plus their sizes from a huge photo-collection.
I have found several similar questions, but not this specific listing.
One did this with the full path name, but I don't need this and it would become very long.
Another lists all files, but without size.
Another lists all filenames with size, but I can't specify a filetype.
This PowerShell command creates the desired list, but I don't know how to limit it to a certain filetype (e.g. .jpg)
gci -rec|?{!$_.PSIsContainer}|%{"$($_.Fullname) $($_.Length)"} >filelist.txt
This batch file lists all .jpg's, but without showing the filesize.
dir /b /s z:\Filme\*.jpg > list1.txt
for /f "tokens=*" %%A in (list1.txt) do echo %%~nxA >> list.txt
del list1.txt
Could anyone edit one of these? so I get the desired list, or come up with a different solution?
Could anyone edit one of these so I get the desired list?
You are almost there with the batch script.
%~z1 will display the file size (in bytes).
You can also get rid of the temporary file by using a slightly different version of the for command.
Use the following batch file:
#echo off
setlocal
for /f "tokens=*" %%A in ('dir /b /s z:\Filme*.jpg') do (
if /i "%%~xf" equ ".jpg" echo %%~nxf %%~zf
) > list.txt
endlocal
Further Reading
An A-Z Index of the Windows CMD command line | SS64.com
Windows CMD Commands (categorized) - Windows CMD - SS64.com
Command Redirection, Pipes - Windows CMD - SS64.com
Dir - list files and folders - Windows CMD - SS64.com
For - Loop through command output - Windows CMD - SS64.com
If - Conditionally perform command - Windows CMD - SS64.com
Parameters / Arguments - Windows CMD - SS64.com
You know about the %%~nxA modifier, so I'm a bit surprised you didn't notice the %%~zA modifier.
To simplify it even more, use a for /R loop and don't use a temp file:
(for /R %%A in (*.jpg) do echo %%~nxA %%~zA)>list.txt
or if you need the full path\name, use %%~fA (explicite) or even just %%A
Text output:
Get-ChildItem -Path 'X:\PHOTO' -Filter '*.jp*g' -Recurse |
Where-Object {-not $_.PsIsContainer} |
Select-Object Name, Length |
Out-File -FilePath '.\FileList.txt'
CSV output:
Get-ChildItem -Path 'X:\PHOTO' -Filter '*.jp*g' -Recurse |
Where-Object {-not $_.PsIsContainer} |
Select-Object Name, Length |
Export-Csv -Path '.\FileList.csv' -NoTypeInformation
P.S. I've used *.jp*g wildcard that will also match *.jpeg files. Unfortunately, * wildcard matches zero or more symbols, so you can get files like zzz.jpXXXg in your list. There are other ways to filter Get-ChildItem output that don't suffer from this issue, such as filtering with pipeline and regex but they're slower: Where-Object {$_.Extension -match '^\.jp[e]{1}g$'}
Another option would be to not use the -Filter parameter, but the -Include instead where the wildcard pattern works as expected, like this:
PowerShell version 3.0 and up
Get-ChildItem 'z:\Filme' -File -Include '*.jpg' -Recurse |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoTypeInformation
PowerShell version below 3.0
Get-ChildItem 'z:\Filme' -Include '*.jpg' -Recurse |
Where-Object { !$_.PsIsContainer} |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoTypeInformation
Note that -Include only works if you also specify -Recurse or if you have the path end in \* like in Get-Childitem 'z:\Filme\*'.
Also, -Filter works faster than -Include (or -Exclude) parameters.
As stated in the docs:
"Filters are more efficient than other parameters, because the provider applies them when the cmdlet gets the objects. Otherwise, PowerShell filters the objects after they are retrieved."
I have never looked into the layout from the Where command, but if it does not alter between languages/locales, or technically if your layout is not too dissimilar to that of my test system, you could do it on your machine like this:
From the Command Prompt:
(For /F "Tokens=1,3*" %A In ('Where/T /R . *.jpg 2^>Nul')Do #Echo("%C","%A")>"list.txt"
From a batch file:
#(For /F "Tokens=1,3*" %%A In ('Where/T /R . *.jpg 2^>Nul')Do #Echo("%%C","%%A")>"list.txt"
Obviously if the layout from your Where command output differs there's still a possibility to adjust the Tokens and/or include delimiters to suit your target system.
In the examples above, I've used . to represent the current directory, you could of course change that to another relative path, e.g. ..\Pictures, or full path, e.g. C:\Users\Patrick\Pictures as necessary.
And a powershell option:
Ls -Filt '*.jpg' -Fo -Rec -EA SilentlyContinue|?{!$_.PSIsContainer -And $_.Extension -Eq '.jpg'}|Select FullName,Length|ConvertTo-CSV -NoT|Select -Skip 1|SC '.\list.txt'
This will also include e.g. system and hidden files, will not include files with extensions other than .jpg and will not include an unrequested header with that listing.
try this
Get-ChildItem "yourdir" -File -Filter '*.jpg' -Recurse |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoType

Powershell ForEach Loop Failing

I'm trying to generate a report for all WIM files in my MDT Deployment Share. Basically, I think need to do a ForEach loop on all the WIM files found. I have what I think should work but, obviously, it doesn't. How far off am I?
$WimPath = "G:\DeploymentShare\Operating Systems"
Get-ChildItem -Path $WimPath -Filter *.wim -Recurse -File | Select-Object -ExpandProperty VersionInfo | Select-Object FileName | ForEach-Object { Get-WindowsImage -ImagePath $_ }
The error I'm seeing is nagging about the Parameter being incorrect for the Get-WindowsImage command.
Get-WindowsImage : The parameter is incorrect.
At line:3 char:147
+ ... t-Object FileName | ForEach-Object { Get-WindowsImage -ImagePath $_ }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'm thinking my Select-Object isn't working like I think it should or I'm not using the pipeline correctly in my Get-WindowsImage command.
I'm a PowerShell noob and don't fully understand this, but I think what is going on can be explained by first focusing on this part of the command:
Get-ChildItem -Path $WimPath -Filter *.wim -Recurse -File | Select-Object -ExpandProperty VersionInfo | Select-Object FileName
To get this far, we first get all the *.wim files in your path, we expand the VersionInfo property, and then select the FileName. In the console, that will show you results like this:
FileName
--------
[files here]
The trick is in understanding what PowerShell is telling you with this output. The fact you see a FileName header means the pipeline has a stream of Objects with one property named FileName. Then we send that stream of Objects to ForEach-Object and look at the $_ special variable.
Hopefully it is clearer now what is going on. Get-WindowsImage -ImagePath $_ wants to see a string value holding the path of a *.wim file. But we sent it an object with one property.
You can fix this a few ways... adding ExpandProperty to the second Select-Object would probably do it. But really there's no reason for two Select-Objects in there at all. I think you could just do this:
Get-ChildItem -Path $WimPath -Filter *.wim -Recurse -File | Select-Object -ExpandProperty FullName | ForEach-Object { Get-WindowsImage -ImagePath $_ }
And the trick here is the string representation you see in the shell from Get-ChildItem doesn't necessarily show every property in the object. There wouldn't be space. The FileName was always there, and you can see it by checking the Get-Member cmdlet, like so:
Get-ChildItem -Path $WimPath -Filter *.wim -Recurse -File | Get-Member

List file names in a folder matching a pattern, excluding file content

I am using the below to recursively list all files in a folder that contains the $pattern
Get-ChildItem $targetDir -recurse | Select-String -pattern "$pattern" | group path | select name
But it seems it both list files having the $pattern in its name and in its content, e.g. when I run the above where $pattern="SAMPLE" I get:
C:\tmp\config.include
C:\tmp\README.md
C:\tmp\specs\SAMPLE.data.nuspec
C:\tmp\specs\SAMPLE.Connection.nuspec
Now:
C:\tmp\config.include
C:\tmp\README.md
indeed contains the SAMPLE keywords/text but I don't care about that, I only need the command to list file names not file with content matching the pattern. What am I missing?
Based on the below answers I have also tried:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | group path | select name
and:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | select name
but it does not return any results.
Select-String is doing what you told it to. Emphasis mine.
The Select-String cmdlet searches for text and text patterns in input strings and files.
So if you are just looking to match with file names just use -Filter of Get-ChildItem or post process with Where-Object
Get-ChildItem -Path $path -Recurse -Filter "*sample*"
That should return all files and folders that have sample in their name. If you just wanted files or directories you would be able to use the switches -File or -Directory to return those specific object types.
If your pattern is more complicated than a simple word then you might need to use Where-Object like in Itchydon's answer with something like -match giving you access to regex.
The grouping logic in your code should be redundant since you are returning single files that all have unique paths. Therefore I have not included that here. If you just want the paths then you can pipe into Select-Object -Expand FullName or just (Get-ChildItem -Path $path -Recurse -Filter "*sample*").Fullname
get-ChildItem $targetDir -recurse | where {$_.name -like $pattern} | select name
To complement Matt's helpful answer:
Specifically, because what you're piping to Select-String are [System.IO.FileInfo] objects - which is what Get-ChildItem outputs - rather than strings, it is the contents of the files represented by these objects is being searched.
Assuming that you need to match only the file name part of each file's path and that your pattern can be expressed as a wildcard expression, you do not need Select-String at all and can instead use Get-ChildItem with -Filter, as in Matt's answer, or the slower, but slightly more powerful -Include.
Caveat:
Select-String -Pattern accepts a regular expression (e.g., .*sample.*; see Get-Help about_Regular_Expressions),
whereas Get-ChildItem -Filter/-Include accepts a wildcard expression (e.g., *sample*; see Get-Help about_Wildcards) - they are different things.
On a side note: If your intent is to match files only, you can tell Get-ChildItem to restrict output to files (as opposed to potentially also directories) using -File (analogously, you can limit output to directories with -Directory).
Group-Object path (group path) will not work as intended, because the .Path property of the match-information objects output by Select-String contains the full filename, so you'd be putting each file in its own group - essentially, a no-op.
When using just Get-ChildItem, the equivalent property name would be .FullName, but what you're looking for is to group by parent path (the containing directory's path), .DirectoryName), I presume, therefore:
... | Group-Object DirectoryName | Select-Object Name
This outputs the full path of each directory that contains at least 1 file with a matching file name.
(Note that the Name in Select-Object Name refers to the .Name property of the group objects returned by Group-Object, which in this case is the value of the .DirectoryName property on the input objects.)
To complement the excellent answer by #mklement0, you can ask Powershell to print the full path by appending a pipe as follows:
Get-ChildItem -Recurse -ErrorAction SilentlyContinue -Force -Filter "*sample*" | %{$_.FullName}
Note: When searching folders where you might get an error based on security, hence we use the SilentlyContinue option.
I went through the answer by #Itchydon
but couldn't follow the use of '-like' $pattern.
I was trying to list files having 32characters(letters and numbers) in the filename.
PS C:> Get-ChildItem C:\Users\ -Recurse | where {$_.name -match "[a-zA-Z0-9]{32}"} | select name
or
PS C:> Get-ChildItem C:\Users\010M\Documents\WindowsPowerShell -Recurse | Where-Object {$_.name -match "[A-Z0-9]{32}"} | select name
So, in this case it doesn't matter whether you use where or where-object.
You can use select-string directly to search for files matching a certain string, yes, this will return the filename:count:content ... etc, but, internally these have names that you can chose or omit, the one you need is the "filename" to do this pipe this into "select-object" choosing the "FileName" from the output.
So, to select all *.MSG files that has the pattern of "Subject: Webservices restarted", you can do the following:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename
Also, to remove these files on the fly, you could pip into a ForEach statement with the RM command as follows:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename | foreach { rm $_.FileName }

How do I find files by their extension in a specific directory and go through them with Power Shell?

I am trying to figure out how I would be able to do it. I have a directory which can be with multiple files, they named differently, but they all have the same extension (.ini). I need to somehow , search files by their extension and then in turn and order replace content's in each of them. Now I figured out how to get file by exact name (not by extension) and replace it's contents
#powershell -command "(Get-Content ..\Folder\File.ini).replace('TextToBeReplaced',\"NewText1`nNewText2") | Set-Content ..\Folder\File.ini"
What do I need to change?
try this:
Get-ChildItem "c:\temp\" -recurse -file -filter "*.ini" |
%{$fullname=$_.fullname; (Get-Content $_.fullname).Replace("oldstring", "newstring") | Set-Content $fullname}
Easiest way is using the -Filter parameter with Get-ChildItem:
Get-ChildItem -Filter *.ext -Recurse