How to create multiple subfolders? - powershell

How do I create a folder structure where I have one root folder, then approximately 9 differently named subfolders; within these subfolders there another set of differently named subfolders. I have already made one .csv file with the script. But I do not feel like writing out 30 lines of the same code to make these subfolders.
Here is what I have so far:
$LogsDir = "D:\Logs"
If (-Not (Test-Path $LogsDir)) {
New-Item -Path $LogsDir -ItemType Directory | Out-Null
} Else {
Write-Host "Directory already exists!"
}
$Subfolders1 = Import-Csv "Subfolders1.csv";
$Subfolders1 | Where-Object {$_.Type -eq 'Subfolder'} |
ForEach-Object {
$Subfolders1 = $_.Name;
New-Item "$LogsDir\$Subfolders1" -ItemType Directory
}
# ******sbf1 = the first set of subfolders******
# ******sf-** = the second set******
New-Item -Path "$LogsDir\sbf1\sf-a1" -ItemType Directory
New-Item -Path "$LogsDir\sbf1\sf-a2" -ItemType Directory
New-Item -Path "$LogsDir\sbf1\sf-a3" -ItemType Directory
New-Item -Path "$LogsDir\sbf2\sf-a1" -ItemType Directory
New-Item -Path "$LogsDir\sbf2\sf-a2" -ItemType Directory
New-Item -Path "$LogsDir\sbf2\sf-b2" -ItemType Directory
I am trying to create a log file folder tree. I think I got some of it down but any help would appreciated.

New-Item will create missing parent folders, so you only need a list of the leaf folders (with full path):
D:\Logs\sbf1\sf-a1
D:\Logs\sbf1\sf-a2
D:\Logs\sbf1\sf-a3
D:\Logs\sbf2\sf-a1
D:\Logs\sbf2\sf-a2
D:\Logs\sbf2\sf-b2
and then create the folders like this:
Get-Content 'C:\path\to\subfolders.txt' | % {
New-Item -Type Directory -Path $_
}

Related

Compress-Archive handle files with same name in Powershell

I'm writing an archiving script which collecting desired files to an array then adding them to an archive 1 by 1.
I came to a problem when there is DIR1/file.ext and DIR2/file.ext because DIR2's file going to overwrite the previous.
How can I set unique filename or how it's possible to solve it on the fly instead of copying files to a dir with structures then zip the whole dir?
Here is my code:
# GET FILE LIST
$outgoingfiles = Get-ChildItem -Depth 1 -Filter "*.EXT" | Where-Object { $_.DirectoryName -like "*OUTGOING*" }
# Handle if OUTGOING/archive dir is exists
if(-not (Test-Path "OUTGOING/archive")) {
New-Item -Path "OUTGOING/archive" -ItemType Directory
}
# ZIP outgoing files
ForEach ($outgoing in $outgoingfiles) {
Compress-Archive $outgoing.FullName -Update -DestinationPath $zippath
}
Thank you!
I don't think there is a way to tell Compress-Archive to rename files when a file with the same name is already included in the zip.
What you can do is create a temporary folder, copy all files to there and if needed rename them. Then create the zip file using the unique files in that folder.
Finally, remove the temp folder again:
$zippath = 'D:\Test\OutGoing.zip' # path and filename for the output zip file
$rootPath = 'D:\Test' # where the files can be found
# create a temporary folder to uniquely copy the files to
$tempFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([Guid]::NewGuid().Guid)
$null = New-Item -ItemType Directory -Path $tempFolder
# create a hashtable to store the fileHash already copied
$fileHash = #{}
# get the list of files and copy them to a temporary folder
Get-ChildItem -Path $rootPath -Depth 1 -Filter '*.EXT' -File | Where-Object { $_.DirectoryName -like "*OUTGOING*" } | ForEach-Object {
$count = 1
$newName = $_.Name
# test if the file name is already in the hash and if so, append a counter to the basename
while ($fileHash.ContainsKey($newName)) {
$newName = "{0}({1}){2}" -f $_.BaseName, $count++, $_.Extension
}
# store this file name in the hash and copy the file
$fileHash[$newName] = $true
$newFile = Join-Path -Path $tempFolder -ChildPath $newName
$_ | Copy-Item -Destination $newFile -Force
}
# append '*.*' to the temporary folder name.
$path = Join-Path -Path $tempFolder -ChildPath '*.*'
# next, get the list of files in this temp folder and start archiving
Compress-Archive -Path $path -DestinationPath $zippath -Update
# when done, remove the tempfolder and files
Remove-Item -Path $tempFolder -Force -Recurse
Hope that helps
I would just copy the files along with their parent directories to a destination folder, then zip it up with Compress-Archive. Then you don't have to worry about making filenames unique.
Demo:
$sourceFolder = "C:\\"
$destinationFolder = "C:\\OUTGOING"
# Create destination folder if it doesn't exist
if (-not(Test-Path -Path $destinationFolder -PathType Container))
{
New-Item -Path $destinationFolder -ItemType Directory
}
# Get all .exe files one level deep
$files = Get-ChildItem -Path $sourceFolder -Depth 1 -Filter *.ext
foreach ($file in $files)
{
# Get standalone parent directory e.g. DIR1, DIR2
$parentFolder = Split-Path -Path (Split-Path -Path $file.FullName) -Leaf
# Create destination path with this parent directory
$destination = Join-Path -Path $destinationFolder -ChildPath $parentFolder
# Create destination parent directory if it doesn't exist
if (-not(Test-Path -Path $destination -PathType Container))
{
New-Item -Path $destination -ItemType Directory
}
# Copy file to parent directory in destination
Copy-Item -Path $file.FullName -Destination $destination
}
# Zip up destination folder
# Make sure to pass -Update for redoing compression
Compress-Archive -Path $destinationFolder -DestinationPath "OUTGOING.zip" -Update -CompressionLevel Optimal

Using Powershell create folder and place file according describe below condition

I have many pdf,png files there name are like as below
I have folder named as 1.a chemistry_sem1-questions_technical_report.png,1.b chemistry_sem1-questions_technical_report.png,2.a chemistry_sem1-answer_technical_report.pdf ,2.b chemistry_sem1-answer_technical_report.pdf and result_sem1-allanswer_technical.pdf I need folder as chemistry(main folder) then after split you get another folder "sem1-questions" then you have file above .
So if you had these file output should be
path of the file =chemistry/sem1-questions/chemistry_sem1-questions_technical_report/1.b chemistry_sem1-questions_technical_report.png
path of the file =chemistry/sem1-questions/chemistry_sem1-questions_technical_report/1.a chemistry_sem1-questions_technical_report.png
path of the file=chemistry/sem1-answer/chemistry_sem1-answer/2.a chemistry_sem1-a_technical_report.pdf
Path of the file=result/sem1-allanswer/result_sem1-allanswer_technical.pdf
Thanks
Run this in the directory with all of the chemistry files you listed:
New-Item '.\chemistry' -ItemType Directory
New-Item '.\chemistry\sem1-questions' -ItemType Directory
New-Item '.\chemistry\sem1-questions\chemistry_sem1-questions_technical_report' -ItemType Directory
New-Item '.\chemistry\sem1-answer' -ItemType Directory
New-Item '.\chemistry\sem1-answer\chemistry_sem1-answer' -ItemType Directory
New-Item '.\chemistry\sem1-allanswer' -ItemType Directory
Get-ChildItem | ForEach-Object {
if($_.Name -like "*sem1-questions*") {
Move-Item $_.FullName -Destination '.\chemistry\sem1-questions\chemistry_sem1-questions_technical_report'
} elseif ($_.Name -like "*sem1-answer*") {
Move-Item $_.FullName -Destination '.\chemistry\sem1-answer\chemistry_sem1-answer'
} elseif ($_.Name -like "*allanswer*") {
Move-Item $_.FullName -Destination '.\chemistry\sem1-allanswer'
}
}

Powershell script to loop through variables multiple times

I have 4 variables and I want a script to execute these variables multiple times my thinking is placing each of the variables in their own file and then loop through the files and have the main script which takes the variables loop it.
I'm wondering if this is smart or if I can do it in a simpler way
basically it looks like this
File1
$SFTP_NAME = "PATH_1"
$CUSTOMER_NAME = "Customer_1"
$BACKUP_LOCATION = "Customer_1"
$IP_ADDRESS = 192.168.159.11
File2
$SFTP_NAME = "PATH_2"
$CUSTOMER_NAME = "Customer_2"
$BACKUP_LOCATION = "Customer_2"
$IP_ADDRESS = 192.168.159.12
Main Script
New-Item -ItemType directory -Path \\ftp\Customers\$SFTP_NAME\$CUSTOMER_NAME
New-Item -ItemType directory -Path \\ftp\Customers\$SFTP_NAME\$CUSTOMER_NAME\$BACKUP_LOCATION
New-Item -ItemType directory -Path \\ftp\Customers\$SFTP_NAME\$CUSTOMER_NAME\$IP_ADDRESS
I recommend one CSV file with four columns:
$configurations = #'
SFTP_NAME,CUSTOMER_NAME,BACKUP_LOCATION,IP_ADDRESS
PATH_1,Customer_1,Customer_1,192.168.159.11
PATH_2,Customer_2,Customer_2,192.168.159.12
'# | ConvertFrom-Csv
#or prepare csv file in Excel and import
#$configurations = Import-Csv Csvfile.csv
$configurations | % {
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)"
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)\$($_.BACKUP_LOCATION)"
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)\$($_.IP_ADDRESS)"
}
Create an array and store your configuration data in it using a custom object. Then loop trough the array and use the data to create your items.
$fileList = #()
$fileList += New-Object psobject -Property #{ "SFTP_NAME"="PATH_1"
"CUSTOMER_NAME"="Customer_1"
"BACKUP_LOCATION"="Customer_1"
"IP_ADDRESS"="192.168.159.11"}
$fileList += New-Object psobject -Property #{ "SFTP_NAME"="PATH_2"
"CUSTOMER_NAME"="Customer_2"
"BACKUP_LOCATION"="Customer_2"
"IP_ADDRESS"="192.168.159.12"}
$fileList | foreach {
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)"
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)\$($_.BACKUP_LOCATION)"
New-Item -ItemType directory -Path "\\ftp\Customers\$($_.SFTP_NAME)\$($_.CUSTOMER_NAME)\$($_.IP_ADDRESS)"
}

Merge two directories keeping any files with same name

I am looking for some help to create a PowerShell script to merge or copy one directory to another that the destination directory has files with the same name as the source.
I need to keep both, the script can append a number to the source file if it has a file of duplicate name in the destination.
Here is a sample script that deals with one file, but I need to set a directory and let it loose recursively on the entire directory.
$SourceFile = "C:\Temp\File.txt"
$DestinationFile = "C:\Temp\NonexistentDirectory\File.txt"
if ((Test-Path $DestinationFile) -eq $false) {
New-Item -ItemType File -Path $DestinationFile -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile
try this
$SourceDir = "C:\Temp"
$DestinationDir = "C:\Temp2\NonexistentDirectory"
#create dir if not exists (dont remove if exist)
New-Item -ItemType Directory -Path $DestinationDir -Force
#get list files destination dir
$DestinationFiles=gci $DestinationDir -File
#loop on file source and create newname for copy while name exist already
gci $SourceDir -File | %{
$counter=0
$name=$_.Name
while ($name -in $DestinationFiles.Name)
{
$counter++;
$name="{0}_{1:d6}{2}" -f $_.BaseName, $counter, $_.Extension
}
Copy-Item -Path $_.FullName -Destination "$DestinationDir\$name"
}

powershell Copying files into new directories - best way

I'm using this answer to try to copy files to a new location using a .csv list where OldName is the current file name and NewName is the new name including filepath.
What is the best way to force the script to generate a new folder according to the new path?
For example:
OldName NewName
A.pdf C:\NewFolder\Anew.pdf
This is my script
$Copies = Import-Csv '.\copies.csv' -Header "OldName","NewName"
foreach($File in $Copies) {
New-Item -Force $File.NewName -Type File
Copy-Item $File.OldName $File.NewName
}
But this overwrites any files that stay in the same folder before they get copied.
Replace the line where you create the directory:
New-Item -Force $File.NewName -Type File
With this:
$NewDir = ($File.NewName -as [System.IO.FileInfo]).DirectoryName
If (-not (Test-Path -Path $NewDir)) {
New-Item -ItemType Directory -Path $NewDir -Force | Out-Null
}