Create 2 child directories inside 3 different child directories - windows

I'm trying to write a simple script that will create a folder and then 3 different folders inside and once that is done each of those 3 different folders should have 2 child folders named 'Phase' (1..2).
I'm trying to loop through the path, i.e the child folders (Project) but I don't know how to implement it, otherwise I can just write the last foreach loop another 3 times but that would be inconsistent.
The structure should be:
C:\Projects\Project1\Phase1
C:\Projects\Project1\Phase2
C:\Projects\Project2\Phase1
C:\Projects\Project2\Phase2
C:\Projects\Project3\Phase1
C:\Projects\Project3\Phase2
The script so far I've written is:
# Path variable
$PhasePath = "C:\Projects\Project1"
# Creating the main directory
mkdir C:\Projects
# Loop from 1-3 and create a subdirectory in - Path C:\Projects using the path variable
1..3 | foreach $_{ New-Item -ItemType directory -Name $("Project" + $_) -Path C:\Projects }
1..2 | foreach $_{ New-Item -ItemType directory -Name $("Phase" + $_) -Path $PhasePath }

this should do
foreach ($project in 1..3){foreach ($phase in 1..2) {new-item -Type Directory "C:\Projects\Project$($project)\Phase$($phase)"}}

Here is one way to do it using the instance method CreateSubdirectory from the DirectoryInfo class:
$initialPath = New-Item C:\Projects\ -ItemType Directory
1..3 | ForEach-Object {
$sub = $initialPath.CreateSubdirectory("Project$_")
$null = 1..2 | ForEach-Object { $sub.CreateSubdirectory("Phase$_") }
}
Combining the interpolated paths is also an alternative using this method, similar to ben's helpful answer, though this might less readable:
$initialPath = New-Item .\Project -ItemType Directory
1..3 | ForEach-Object {
foreach($i in 1..2) {
$null = $initialPath.CreateSubdirectory("Project$_\Phase$i")
}
}

Related

how to copy files based on filename lenght using powershell

I need to batch copy a sort of file extensions from subfolders to specific folders for each location.
All folders have a 6 digit number
let's say folder Rood folder: BATCH
Subfolder 1: 000000
Subfolder 2: 111111
despite their extensions, most files have the name as the subfolder but some of them may have extra alphanumeric characters, therefore the script should grab only the ones that are not larger than 6 digits.
Example Subfolder1: 000000.pdf 000000.eps the script would need to grab all pdf within subfolders and export them to a PDF exclusive new folder, and the same would apply for eps files.
I know nothing about powershell but I know that something like this would work for an specific subfolder but I'm still missing the parts where it distributes them to a new PDFONLY and EPSONLY folders and the fact the I want to apply this to all the folders whiting the root folder.
Get-ChildItem -Path "C:\BATCH\*" -Include *.pdf,*.eps -Recurse | Copy-Item -Destination D:\
You can use Group-Object to group all the files by their extension and then loop over each group of objects, create a new folder with the desired name and lastly copy all objects of each group to their folders.
$target = 'D:\' # Set destination here
Get-ChildItem -Path C:\BATCH\* -Include *.py, *.ps1 -Recurse |
Group-Object Extension | ForEach-Object {
# Example of `$folderName` would be `PDF ONLY`
$folderName = '{0} ONLY' -f $_.Name.TrimStart('.').ToUpper()
$destination = Join-Path $target -ChildPath $folderName
# If the `$destination` folder doesn't exist
if(-not (Test-Path $destination)) {
# Create it
$null = New-Item $destination -ItemType Directory
}
Copy-Item -LiteralPath $_.Group.FullName -Destination $destination
}
Similar to Santiago's answer but with an extra filter and without grouping you can do this:
$destination = 'X:\somewhere'
Get-ChildItem -Path "C:\BATCH" -Include '*.pdf','*.eps' -File -Recurse |
Where-Object {$_.BaseName -match '^\d{6}$' } | # filter files with a BaseName of just 6 digits
ForEach-Object {
$targetPath = Join-Path -Path $destination -ChildPath ('{0}ONLY' -f $_.Extension.TrimStart(".").ToUpper())
# make sure the target path exists
# for directories, using the -Force switch either creates a new folder
# or returns the DirectoryInfo object of an existing folder.
$null = New-Item -Path $targetPath -ItemType Directory -Force
$_ | Copy-Item -Destination $targetPath
}

Powershell - create directories form files in a dierectory

I am trying to clean up and group files in a directory by creating subdirectories and then copying the files into the new directories.
Example:
test01.a.jpg
test01.a.txt
test01.b.bak
test01.b.txt
test02.a.txt
test02.a.jpg
test02.a.bak
test03.a.txt
test03.a.bak
test03.b.txt
I wish to create subdirectories like test01, test02, test03 and ideally copy the relevant files over. All groups will have a txt file but more or less of the others.
To create the directories I have got as far as
gci -file *.txt | New-Item -ItemType directory $_.name
which doesn't work as expected.
If your files have names like that, you can simply split the filename on the dot and take only the first part as new folder name.
Then test if a subfolder like that already exists (if not create it) and move the file.
Something like this
$sourcePath = 'D:\Test' # put the real path to the files here
# if you want only the files with extension .txt, use filter '*.*.txt'
(Get-ChildItem -Path $sourcePath -File -Filter '*.*.*') | ForEach-Object {
# use the first part of the file name for subdirectory name
$destinationPath = Join-Path -Path $sourcePath -ChildPath $_.Name.Split(".")[0]
if (!(Test-Path -Path $destinationPath -PathType Container)) {
# if a subdirectory with that name does not already exist, create it
$null = New-Item -Path $destinationPath -ItemType Directory
}
# now move the file to that (new) destination folder
$_ | Move-Item -Destination $destinationPath
}
Actually, algorithm is simple (we don't need to previously compare names of files. All we need is just use a $_.BaseName property)
<#Creating folders and moving files using BaseName property #>
gci *.txt | % { new-item -ItemType Directory -Path ($_.Directory.ToString() + "\" + $_.BaseName.ToString())}
gci -file | % { Move-item $_.Fullname ($_.Directory.ToString() + "\" + $_.BaseName.ToString())}

Create directory with several subfolders in PowerShell? (I know how to do it in Bash)

I want to do the following in PowerShell, but it seems like the curly brackets pose an issue.
Here's how I would do it in Bash:
mkdir -p /path/to/dir/{dir1,dir2,dir3...dir10}
This creates a parent directory, then several directories of which "dir" contains several subfolders.
This should work for you
New-Item -ItemType Directory C:\temp1\dir1,C:\temp1\dir2,C:\temp1\dir3
one more way
$dirs = 1..10
$dirs | % {
New-Item -ItemType Directory ( Join-Path -Path 'c:\temp\dir' -ChildPath ('dir' +$_ ) )
}
If you are after Directories 1 to 10 (or similar) - something like the following will work for you:
1..10 | ForEach {
New-Item -ItemType Directory -Path ("C:\Temp\Dir" + $_)
}
If you are looking to create an array of named subfolders - the something like the following will work (including the ability to create sub-sub-folders:
$subFolderNameArray = #(
"folder1",
"Folder2",
"Folder1\Subfolder3"
)
ForEach ($subFolderName in $subFolderNameArray) {
New-Item -ItemType Directory -Path ("C:\Temp\" + $subFolderName)
}
This relies on creating the folders in teh correct order (you must create parent folders before subfolders). If you want to do things out of order (or can't guarantee the starting array will be tree-wise) - you can use the force switch:
New-Item -ItemType Directory -Path ("C:\Temp\Folder\Subfolder") -Force

Delete All But The Newest File of Pattern In Each Subdirectory

Requirements:
Iterate through all folders and files in each directory
Delete all files in each subdirectory except for the newest one (contains filename time stamp) and has a specific filename pattern or instead copy the one file in each subdirectory that is the newest and that is preceded with LIVE_DATA. (There are other files in each subdirectory I wish to ignore).
Directory: AISI-301.0000000001006165.2015-08-24_23-57-46-1
File: LIVE_DATA_2015-08-24_23-57-51.413+0000.MCA
How can I iterate through all of the files recursively while doing comparisons between files in each subdirectory only? I don't want to compare all of them together. Just the one's inside each subdirectory.
for $filename in Get-ChildItem -recurse {
for $filename in $directory {
if ($filename > $filename2) {
$temp = $filename
}
$filename2 = $filename1
}
}
This is what I ended up using to rename my file's after the directory names. It appends the file name to the end and the directory name comes first. I hope this helps somebody else that might be searching for this solution.
Get-ChildItem -include *LIVE_DATA_*.MCA -recurse | Rename-Item -NewName { $_.Directory.Name+'_'+$_.Name}
If you want to remove all files LIVE_DATA_* except the most recent one on a per-folder basis you could do something like this:
$root = 'C:\path\to\root\folder'
Get-ChildItem $root -Recurse | ? { $_.PSIsContainer } | ForEach-Object {
Get-ChildItem (Join-Path $_.FullName 'LIVE_DATA_*') |
Sort-Object Name -Desc |
Select-Object -Skip 1 |
Remove-Item -Force
}
Get-ChildItem $root -Recurse | ? { $_.PSIsContainer } lists all subfolders of $root. Then the ForEach-Object runs another Get-ChildItem statement (without recursion) for each subfolder separately. The Join-Path statement builds a wildcard path from the filename pattern and the full path to the folder (C:\path\to\root\folder\sub\folder\LIVE_DATA_*).
Basically the code lists all folders, then processes the files for each individual folder.

How to list files with a for loop?

How I can do a ls using PowerShell?
for i in `ls`
do
if [ -d $i ] #miro si és directori
then
echo "Directory"
else echo "File"
fi
done
POWERSHELL
$llistat -ls
forEach $element in $llistat ??? this is possible
}
A more PoSh way is to use a pipeline, and perhaps a hashtable:
$type = #{
$true = 'Directory'
$false = 'File'
}
Get-ChildItem | ForEach-Object { $type[$_.PSIsContainer] }
PowerShell even has a default alias ls for Get-ChildItem, so you could use more Unix-ish syntax:
ls | % { $type[$_.PSIsContainer] }
In PowerShell, the Get-ChildItem cmdlet works like ls (at least with the file system provider). All items returned have a PowerShell-specific property called PSIsContainer, indicating whether it's a directory or not:
foreach($item in (Get-ChildItem)){
if($item.PSIsContainer){
"Directory"
} else {
"File"
}
}
If you want to see what's inside each directory, one level down:
foreach($item in (Get-ChildItem)){
if($item.PSIsContainer){
# Directory! Let's see what's inside:
Get-ChildItem -Path $item.FullName
}
}
As of PowerShell version 3.0 and up, the Get-ChildItem supports a File and Directory switch on the filesystem provider, so if you ONLY want directories, you could do:
Get-ChildItem -Directory
So the second example becomes:
Get-ChildItem -Directory | Get-ChildItem
You could also list files recursively (like ls -R):
Get-ChildItem -Recurse

Resources