Powershell v5 Get-ChildItem -File not working? - powershell

Get-ChildItem -Path $dir -Recurse -File | ForEach-Object `
{
Write-Host $_.fullname
}
Get-ChildItem : A parameter cannot be found that matches
parameter name 'File'.
Version
-------
5.1.17763.771
I have many other ps scripts running that use this and it works fine, but for some reason it's not working in this new script I wrote. What's going on?

Thank you everyone for helping.
The value of $dir was
" S:\folder\folder\"
Removing the space before the drive letter resolved the issue.

In addition to the OP's particular instance, there are other cases where this error can occur. Get-ChildItem can be used on other providers besides the file provider (e.g., the registry), and the -File switch is not valid in those cases.
Example:
$dir = 'C:\Temp'
Get-ChildItem -Path $dir -File # Works just fine
$dir = 'HKCU:\Software'
Get-ChildItem -Path $dir # Works without -File switch
Get-ChildItem -Path $dir -File # Throws "parameter cannot be found" error

That wasn't the source of the problem for me.
All I did was surround the variable with ( ) and that resolve it.
In my case I wanted the full filename of the 'found' file
$curdir = "C:\Program Files\"
(Get-Childitem -Path ($curdir) -File -filter "node.exe" -recurse -Force -ErrorAction SilentlyContinue).Directory.FullName
In your case I'm sure just using this would work for you:
Get-ChildItem -Path ($dir) -Recurse -File | ForEach-Object `
{
Write-Host $_.fullname
}

Related

Powershell folder archiving

I have a powershell script that simply uses the Get-ChildItem command to search through a directory for a folder matching a keyword. When found I need it to zip it and leave it right in that same directory.
Here's what I've tried by piping the command into both 7zip and the native compress:
set-alias zip "$env:ProgramFiles\7-Zip\7z.exe"
Get-ChildItem $path "keyword" -Recurse -Directory | zip a
AND
Get-ChildItem $path"keyword" -Recurse -Directory | compress-archive
Both times it always asks for a source and destination which is hard to define since I'm having it search through a drive with many sub-folders. I though using the pipe would imply the source as well.
Any ideas? Thanks!
EDIT:
I suppose I could set the Get-ChildItem to a variable and use that as the "source" and have the destination be a generic location for them all but I'd have to name them differently, no?
Give this a try:
$path = "INSERT SOURCE ROOT"
foreach ($directory in Get-ChildItem $path -Recurse -Directory -Filter "keyword"| Select-Object FullName | foreach { $_.FullName}) {
$destination = Split-Path -Path $directory -Parent
Compress-Archive -Path $directory -DestinationPath $destination
}
This is looking inside the path for anything matching the "keyword", going up 1 level, and then zipping the found file.
With temp and temp2 directories under C:\ this is working for me (note that the directories must have content):
Get-ChildItem "C:\" "temp*" -directory | compress-archive -DestinationPath "C:\tempzip.zip"
It zips all directories found to C:\tempzip.zip.
I believe what you actually want is:
$dirs = Get-ChildItem "C:\" "temp*" -directory
foreach ($dir in $dirs){
compress-archive $dir.fullname -DestinationPath "$($dir.fullname).zip"
}
Note that I omitted -recurse for my testing.
You can do this:
get-childitem -path "The Source Path" -recurse | where {$_.Name -match "Keyword"} | foreach {
$parent = Split-Path -Path $_ -Parent
Compress-Archive -Path $_ -DestinationPath $parent
}

Error reading file share paths as arguments

I am receiving the following error when I execute the below script.
Test-Path : A positional parameter cannot be found that accepts
argument 'input.dat'.
.\FL.ps1 \\flamingdev\analytics\source\INBOUND \\flamingdev\analytics\source\OUTBOUND
[CmdletBinding()]
param (
[string] $SrcFolder,
[string] $FileListPath
)
$SrcFolder
$FileListPath
IF (Test-Path "$FileListPath"\input.dat) {
Remove-Item "$FileListPath"\input.dat
}
Get-ChildItem -File -Path "$SrcFolder"\Extract* | Select-Object - ExpandProperty Name | Add-Content -Path "$FileListPath"\input.dat
You meed to take "all path" in double quotes. Like this:
IF (Test-Path "$FileListPath\input.dat") {
Remove-Item "$FileListPath\input.dat"
}
Get-ChildItem -File -Path "$SrcFolder\Extract*" | Select-Object -ExpandProperty Name | Add-Content -Path "$FileListPath\input.dat"
Thank you, issue was resolved after tweaking the code little bit. Get-ChildItem -File -Path "$SrcFolder","*.csv"

Get only file with given extension in directory

I have a string variable pointing to a directory. In this directory is a single file with the extension .xyz. How do I get the path to this file, without knowing the file name itself?
I have the following code so far:
$dir = "C:\Temp\MyDir"
$xyzFiles = #(Get-ChildItem "$dir\*.xyz")
$file = $xyzFiles[0]
Is this "the way to go" in PowerShell? Is there a better solution?
I would recommend using Get-ChildItem's -include parameter:
Get-ChildItem $dir -include *.xyz
I would use Get-ChildItem -Filter and Select-Object -First:
$filepath = Get-ChildItem -Path $dir -Filter *.xyz |Select -First 1
Simplest solution:
Get-ChildItem $dir -File '*.xyz'
In powerShell version 5, you can also try this:
Get-ChildItem $dir -Recurse -Include *.xyz
You can use the pipeline feature in Powershell to be a bit more efficient:
Get-ChildItem "$dir" | Where-Object {$_.FullName -match ".xyz$"}
This will grab a file with the extension of .xyz. If you have more than file you can further narrow it down.
You could also try Get-Item -LiteralPath (Resolve-Path "$dir\*.xyz")
This should work:
Get-ChildItem $dir -File | Where-Object { $_.Extension -eq ".xyz" }

Splatting with Move-Item gives an error

Ok, so the script itself is over 500 lines long, so I'll refrain from posting the entire thing. However, I have narrowed down the issue to a single line.
If I use the below line of code, everything works as expected.
Move-Item -Path $path -Include *.txt,*.doc,*.pdf -Destination $dest -Force
But when I change it to use splatting, it gives me an error
$downloadDir = "G:\Downloads"
$dest = "G:\Test\"
$editList = Get-ChildItem -LiteralPath "$downloadDir" -include "[" -File | ForEach-Object -Process {Rename-item -LiteralPath $_.FullName -NewName ($_.Name -replace "[][]"," ") -ErrorAction SilentlyContinue}
$mainList = Get-ChildItem -Path "$downloadDir" -File | Select-Object Name
ForEach ($list in $mainList) {
$item = $list.Name
$path = "$downloadDir\*"
$opts = #{
Path = $path;
Include = '*.txt,*.doc,*.pdf';
Force = $true;
Destination = $dest
}
Move-Item #opts
}
Move-Item : Cannot move item because the item at 'G:\Downloads\test.txt' does not exist.
I feel like I am probably missing something very basic, but I don't know enough about hash tables/splatting yet, to spot the mistake.
Any ideas?
EDIT:
Just to clarify, G:\Downloads\test.txt comes from $path which is generated from a Get-ChildItem.
I am literally doing a straight swap of the 2 versions of code(Splatting/Non-splatting).
EDIT 2:
Added all the parts of the script relevant to that Move-Item
EDIT 3:
Got this working by using double quotes for the "Include" line:
Include = "*.txt","*.doc","*.pdf";
Change your Include from:
Include = '*.txt,*.doc,*.pdf';
to
Include = "*.txt","*.doc","*.pdf";
The Path statement can be tricky as well.
For example
get-childitem c:\temp -include *.txt
will not work, while
get-childitem c:\temp\* -include *.txt
will work, if you have any .txt files in c:\temp
It's stupid, but that's how it is with some of these cmdlets.

How to write a PowerShell function to get directories?

Using PowerShell I can get the directories with the following command:
Get-ChildItem -Path $path -Include "obj" -Recurse | `
Where-Object { $_.PSIsContainer }
I would prefer to write a function so the command is more readable. For example:
Get-Directories -Path "Projects" -Include "obj" -Recurse
And the following function does exactly that except for handling -Recurse elegantly:
Function Get-Directories([string] $path, [string] $include, [boolean] $recurse)
{
if ($recurse)
{
Get-ChildItem -Path $path -Include $include -Recurse | `
Where-Object { $_.PSIsContainer }
}
else
{
Get-ChildItem -Path $path -Include $include | `
Where-Object { $_.PSIsContainer }
}
}
How can I remove the if statement from my Get-Directories function or is this a better way to do it?
Try this:
# nouns should be singular unless results are guaranteed to be plural.
# arguments have been changed to match cmdlet parameter types
Function Get-Directory([string[]]$path, [string[]]$include, [switch]$recurse)
{
Get-ChildItem -Path $path -Include $include -Recurse:$recurse | `
Where-Object { $_.PSIsContainer }
}
This works because -Recurse:$false is the same has not having -Recurse at all.
In PowerShell 3.0, it is baked in with -File -Directory switches:
dir -Directory #List only directories
dir -File #List only files
The answer Oisin gives is spot on. I just wanted to add that this is skirting close to wanting to be a proxy function. If you have the PowerShell Community Extensions 2.0 installed, you already have this proxy function. You have to enable it (it is disabled by default). Just edit the Pscx.UserPreferences.ps1 file and change this line so it is set to $true as shown below:
GetChildItem = $true # Adds ContainerOnly and LeafOnly parameters
# but doesn't handle dynamic params yet.
Note the limitation regarding dynamic parameters. Now when you import PSCX do it like so:
Import-Module Pscx -Arg [path to Pscx.UserPreferences.ps1]
Now you can do this:
Get-ChildItem . -r Bin -ContainerOnly