Not too long ago I came across a PowerShell snippet, probably via Twitter, that showed how to use a few classes from the System.IO namespace to create dummy files. Sadly I forgot the record where I saw this first mentioned. What I liked about the code I saw was the ability to create a dummy file of any size. You're probably wondering why you would ever want to do this. Way, way back in the day when storage was expensive I used to create a few 100MB of dummy files using an old command line utility which I think was called creatfil.exe. The reasoning was that if the server started running out of disk space unexpectedly, I could delete the dummy files and buy myself a little time and breathing room. Fortunately, I think we've advanced where that technique is no longer necessary.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
But, where you might want some dummy or sample files, is to simulate a user folder with a variety of files. You could use this test directory to hone your PowerShell scripts. Any you may have your own reasons for needing a bunch of sample files. So I took the original code and ran with it, as I usually do. I came up with a function called New-SampleFile.
#requires -version 4.0 Function New-SampleFile { <# .SYNOPSIS Create sample files .DESCRIPTION This command will create sample, or dummy files of random sizes in the folder you specified. .PARAMETER Path The folder where the files will be created. The default is the current location. .PARAMETER Filename You can specify a filename or let the function create a random name. .PARAMETER MaximumSize The maximum file size in bytes for the sample file. The minimum is 5 bytes. .PARAMETER Force Overwrite existing files with the same name. .PARAMETER Passthru Write the new file to the pipeline. .EXAMPLE PS C:\> new-samplefile -path c:\files -filename fileA.txt Create a random sized file called FileA.txt in C:\files. .EXAMPLE PS C:\> (1..5).foreach({new-samplefile -path c:\work -Filename "file$_.txt" -Passthru -MaximumSize 1kb -Force}) Directory: C:\work Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 1/20/2015 9:11 AM 296 file1.txt -a--- 1/20/2015 9:11 AM 22 file2.txt -a--- 1/20/2015 9:11 AM 979 file3.txt -a--- 1/20/2015 9:11 AM 320 file4.txt -a--- 1/20/2015 9:11 AM 855 file5.txt Create 5 files, file1.txt to file5.txt under C:\work with a maximum size of 1KB. .NOTES NAME : New-SampleFile VERSION : 1.0 LAST UPDATED: 1/20/2015 AUTHOR : Jeff Hicks (@JeffHicks) Learn more about PowerShell:Essential PowerShell Learning Resources**************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .INPUTS None .OUTPUTS System.IO.FileInfo #> [cmdletbinding(SupportsShouldProcess)] Param( [Parameter(Position=0)] [string]$Path=".", [string]$Filename = [System.IO.Path]::GetRandomFileName(), [ValidateNotNullorEmpty()] [int]$MaximumSize = 100KB, [switch]$Force, [switch]$Passthru ) Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" #validate path to make sure it is valid and a FileSystem path if ((Test-Path $Path) -AND ((Resolve-Path $path).Provider.Name -eq 'FileSystem')) { #define the output path $Output = Join-Path -Path (Convert-Path $path) -ChildPath $Filename #delete existing file if found and using $Force, otherwise #the function will throw an exception if ($Force -AND (Test-Path -Path $Output)) { Write-Verbose "Deleting existing file" Remove-Item -Path $Output } #if $force and output file exists #generate a random file size $Size = Get-Random -Minimum 5 -Maximum $MaximumSize Write-Verbose -message "Creating $output with size $Size" if ($PSCmdlet.ShouldProcess($Output)) { $stream = New-Object System.IO.FileStream($Output, [System.IO.FileMode]::CreateNew) $stream.Seek($Size, [System.IO.SeekOrigin]::Begin) | Out-Null $stream.WriteByte(0) $Stream.Close() Write-Verbose "File created." if ($Passthru) { Get-Item -Path $Output } } #close should process } #if path test else { Write-Warning "Could not verify $(Convert-path $Path) as a filesystem path." } Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end New-SampleFile function
The function will create a randomly sized file in the specified folder. The default is the current location. As you look through the code you'll see I've added a test to verify the path and to make sure it is a FileSystem path and not something like the registry. Also by default the function will use a randomly generated file name which will be something like rcstwqyg.34e. Personally, I'm going to specify a filename. The function will create the file of a random size between 5 bytes and the value of the MaximumSize parameter, which has a default of 100KB.
The function will not overwrite existing files unless you use –Force. Nor will you see any output unless you use –Passthru. Even those are common parameters, I had to write the PowerShell expressions to implement them. The same is true of –WhatIf. You'll see in the cmdletbinding attribute that the function supports ShouldProcess. However, the .NET classes I'm calling have no concept of WhatIf. I had to handle that myself
if ($PSCmdlet.ShouldProcess($Output)) { $stream = New-Object System.IO.FileStream($Output, [System.IO.FileMode]::CreateNew) $stream.Seek($Size, [System.IO.SeekOrigin]::Begin) | Out-Null $stream.WriteByte(0) $Stream.Close() Write-Verbose "File created." if ($Passthru) { Get-Item -Path $Output } } #close should process
Here's the function in action:
This also makes it easy to create multiple files.
1..10 | foreach { new-samplefile -Path c:\work -Filename "TestFile_$_.dat" -passthru -MaximumSize 50KB}
Or how about this? I want to create a variety of files with different names.
$extensions = ".txt",".docx",".xlsx",".pdf",".pptx",".doc",".png",".mp3" $names = "sales","data","marketing","file","demo","test","finance","HR","MFG","project" $path = "C:\SampleFiles" 1..10 | foreach { $file = "{0}_{1}{2}" -f (Get-Random -InputObject $names),(Get-Random -Minimum 10 -Maximum 1000),(Get-Random -InputObject $extensions) New-SampleFile -Path $path -Filename $file -Passthru –Force }
Now I have some test files I can work with
Normally I prefer to use cmdlets wherever possible. But since there is no cmdlet from Microsoft to create dummy files, I have no problem resorting to the .NET Framework. However, I think it is still worth the time to wrap the .NET commands in a user-friendly and easy to use advanced function as I've done today.
If you find a way to use this function, I hope you'll let me know.
I’m all about doing things with PowerShell but sometimes I think its easier to just keep it simple. That’s a lot of code to generate empty files when fsutil can do it so much easier.
fsutil file createnew ([System.IO.Path]::GetRandomFileName()) (get-random -Minimum 5KB -Maximum 100KB)
I use it frequently when I need files to test network speeds.
~NC
Yes it is a lot of code but with a purpose or “value-add” like support for Whatif. But sure, if you need to get something done quickly from the command prompt there’s nothing wrong with your approach.