To read a text file and create a new file for each line in PowerShell, use the
Get-Content cmdlet to retrieve the lines, then pipe them into a
Foreach-Object loop. Inside the loop, use
Set-Content or
New-Item combined with
Out-File to generate individual files named after or containing the content of each line. This approach automates batch file creation efficiently without manual intervention.
Understanding the Core Cmdlets
The primary command for reading text files in PowerShell is
Get-Content. When you run this command against a file, it returns an array of strings, where each string represents a single line from the source document. For example, if you have a file named
list.txt containing three names,
Get-Content list.txt will return a collection of those three names.
Once you have this collection, you need to iterate through it. The
Foreach-Object cmdlet (often aliased as
%) allows you to process each item in the pipeline individually. This is crucial because you want to perform a distinct action—creating a new file—for every single line, rather than processing the entire file as one block.
For writing output,
Set-Content is the standard choice. It overwrites the target file if it exists, which is useful for ensuring clean outputs. Alternatively,
New-Item can be used to explicitly create the file structure before writing to it, though
Set-Content often handles file creation implicitly if the path does not already exist.
Creating Files Based on Line Content
A common scenario is creating a new empty file for each line, using the line itself as the filename. Suppose your input file
users.txt contains:
Alice
Bob
Charlie
You can achieve this with the following script:
Get-Content -Path "C:\Data\users.txt" | ForEach-Object {
$line = $_
$fileName = "$line.txt"
Set-Content -Path "C:\Output\$fileName" -Value ""
}
In this code,
$_ represents the current object in the pipeline, which is the current line being processed. We assign this to a variable
$line for clarity. Then, we construct the full path for the new file. Finally,
Set-Content creates the file at that path. The
-Value "" argument ensures the file is created but remains empty. If you wish to populate the new file with the line's content, simply replace
-Value "" with
-Value $line.
It is important to note that special characters in filenames can cause errors. If your lines contain characters invalid for Windows filenames (such as
:,
*, or
?), the script will fail. You may need to sanitize the filename. For guidance on cleaning up file names, see
How to Remove Special Characters from Folder Names in Windows 10.
Handling Complex File Structures
Sometimes, you might not want to use the line content as the filename but instead want to create a structured directory or file based on specific logic. For instance, you might want to add prefixes or suffixes to the generated files.
Get-Content -Path "input.txt" | ForEach-Object {
$content = $_
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$newName = "backup_${timestamp}_${content}.txt"
$content | Set-Content -Path "C:\Backup\$newName"
}
This example demonstrates how to inject dynamic data, such as timestamps, into your file naming convention. This is particularly useful when generating logs or backup files where uniqueness is required.
If you are dealing with large files, performance can become a concern.
Get-Content loads the entire file into memory by default. For very large files, consider using
Get-Content -ReadCount 0 or streaming methods to reduce memory footprint. However, for typical text lists under a few thousand lines, the standard method is sufficient and fast.
Another consideration is error handling. If a line in your source file is null or empty, it might result in an empty filename or a validation error. You can filter these out by adding a condition inside the loop:
if ($line -and $line.Trim() -ne "") {
# Create file logic here
}
This ensures that blank lines in the source text do not produce useless empty files in the output directory.
Advanced Scenarios and Troubleshooting
When working with PowerShell scripts, you might encounter issues related to execution policies or permissions. If you receive an error stating that the script cannot be loaded, check your execution policy settings. While this article focuses on file I/O, general script execution issues are covered in
Command Prompt Drive Switching Different From PowerShell and
Troubleshooting PowerShell Get-Appx -AllUsers Failure, which provide context on environment-specific quirks.
Additionally, if you are trying to set targets for shortcuts or links based on these lines, the logic remains similar, but you would use different cmdlets like
New-Item with the
-ItemType Link parameter. For more details on managing links programmatically, refer to
How to Set the Target of a .lnk File Programmatically with PowerShell or C++.
Always test your scripts on a small subset of data first. Create a temporary directory and a small test file to verify that the file paths are constructed correctly and that no unexpected characters break the file creation process. This precaution saves time and prevents clutter in your production directories.
Frequently Asked Questions
What happens if a line in my text file is empty?
If a line is empty, the script will attempt to create a file with an empty name or just the extension, which usually results in an error. To prevent this, always check if the line is null or whitespace before proceeding with file creation.
Can I use this method to copy existing files instead of creating new ones?
Yes, you can modify the script to use
Copy-Item instead of
Set-Content. You would define a template file and copy it to a new location named after each line in your source text file.
How do I handle files with special characters in their names?
PowerShell will throw an error if you try to create a file with invalid characters like
/,
\,
:, etc. You must sanitize the filename by replacing these characters with safe alternatives like underscores or hyphens before passing the path to
Set-Content.
Is there a performance limit for the number of lines?
While PowerShell can handle millions of lines, memory usage increases with the size of the input file because
Get-Content loads all lines into an array. For extremely large files, consider processing the file in chunks or using streaming techniques to avoid OutOfMemory exceptions.
How can I ensure the output directory exists before creating files?
You should always check for the existence of the output directory using
Test-Path. If it does not exist, use
New-Item -ItemType Directory to create it before attempting to write any files into it.