Well, there are a few issues with your code, but first I'll answer the questions you asked.
1. Ask the user for a directory, and use a default directory if nothing is entered
To have a function use a default value for any parameter, simply add = defaultvalue
at the end of the parameter declaration. In this case,
param (
$Path = 'C:\My\Default\Directory'
)
If you don't want the function to use a default directory, but want the script to assign the default directory when prompting the user, you can do it this way:
if (! ($a = Read-Host 'Enter directory')) {
$a = 'C:\My\Default\Directory'
}
The if condition executes $a = Read-Host 'Enter directory'
, and executes the block that assigns a default value to $a if the user doesn't enter anything (an assignment statement evaluates to the value assigned to the variable, and an empty string is a false value, so (! ($a = Read-Host 'Enter directory'))
is true if the user hits Enter without providing a value).
2. Find the largest value in the directory
The command you were given works:
Get-ChildItem c:\temp | Sort Length -desc | Select-Object -First 1
You say it does nothing in your code, but I don't even see it in your code. If you show where/how you tried to add it, I'll be able to tell you why it appears to do nothing. It probably has something to do with how you're trying to use the results. For now I can explain how it works.
Get-ChildItem C:\Temp |
lists the contents of C:\Temp, of course, and sends the results (FileInfo objects representing each item in the directory) to the pipeline.Sort Length -desc |
sorts the results in descending order, and sends the sorted results down the pipeline. Sort is shorthand for Sort-Object, Length is the property of a FileInfo object that contains the file size in bytes, and -desc is an abbreviation of -Descending.Select-Object -First 1
selects the first item from the results. Since they're sorted by file size in descending order, the first item is a FileInfo object representing the largest file.
Some other issues with your code not directly related to the question
PowerShell is designed to work with pipelines. Instead of
foreach ($Folder in (Get-ChildItem $Path)) {
use
Get-ChildItem $Path | %{
It's more efficient in terms of both typing and processing. %{} is an abbreviation for ForEach-Object (which is not the same as a foreach loop; it's a filter for use in pipelines, and it generally runs more efficiently).
$Size/100
won't give you the size in KB because 1 KB is 1024 bytes, but there's a built-in shorthand for that:$Size / 1KB.
You can also use
1MB
,1GB
,1TB
,1PB
(sorry, there is no1EB
yet, but I'm sure in 5-10 years not only will there be one, it will probably be very frequently used). Note that you can change the coefficient, but you can't leave it out (/ 2GB
divides by 2 gigabytes, but/ GB
without the1
is a syntax error)There's no need to use a recursive function to do this. PowerShell has built-in facilities for recursively walking a directory tree and for summing results. Here's a version showing how to do that, combined with the suggestions made above:
function Get-Size { param ( $Path = 'C:\My\Default\Directory' ) Get-ChildItem $Path -Recurse | ?{$_.PSIsContainer} | %{ $Size = (Get-ChildItem $_.FullName | Measure-Object Length -Sum -ea SilentlyContinue).Sum New-Object PSObject -Property @{'Size in KB' = ($Size / 1KB); 'Folder' = $_.FullName} } }
The output will be rather messy, so you'll probably want to pipe the results to Format-Table. I think it's better practice to do your formatting when you call the function rather than include it in the function definition itself. This will give you the properties in the order you probably want, with the size right-aligned and fixed at a precision of two decimal places:
Get-Size $a | Format-Table @{Name = 'Size in KB'; Expression = {"{0:N2}" -f $_.'Size in KB'}; Align = 'right'}, ' ', Folder -AutoSize