the paths are like this and none of these directory exist:
"D:\temp\test\abc.txt"
"D:\temp2\test2\abc2.txt"
"D:\temp1\abc.txt"
I am trying to split the path and create directories only.
I am trying below:
New-Item -Path "D:\temp\testing\abc.txt" -ItemType file
Split-Path -Path "D:\temp\testing\abc.txt" -Resolve –IsAbsolute
[edit - didn't see the comment by Tuttu. [*blush*] i will leave this here, but that one is the 1st answer.]
i think what you are looking for is the Split-Path cmdlet. [grin] something like this ...
$PathList = #(
'c:\temp\test1\abc.txt'
'c:\temp\test2\subtest2-1\abc2.txt'
'c:\temp\test3\subtest3-1\subtest3-1-1\abc.txt'
)
foreach ($PL_Item in $PathList)
{
$NewDir = Split-Path -Path $PL_Item -Parent
if (-not (Test-Path -LiteralPath $NewDir))
{
$Null = New-Item -Path $NewDir -ItemType Directory -Force
}
}
that made 3 new directories, two of them with sub-directories.
note that this does NOT take into account any input path that has no terminating file ... you will always get the parent path.
Related
When I try to import a CSV, and take a source filename/path and destination folder ref, copy-item seems to not copy the file in question.
I have a folder full of files in C:\Dir1\Test\Files\ and I need to copy them to individual folders in C:\Dir1\Test, based on what is in the csv.
$SourceDir = 'C:\Dir1\Test\Files\'
$DestDir = 'C:\Dir1\Test\'
Import-Csv C:\Dir1\Test\FileList.csv | ForEach-Object {
$Source = $SourceDir + $($_.'FilePath')
$Dest = $DestDir + "$($_.'Folder Ref')\"
Copy-Item $Source -Destination $Dest
}
If I switch out the Copy-Item to Write-Host, it reads to me correctly, am I doing something wrong?
Nothing happens, it returns me to the prompt with no output
Constructing file paths using string concatenation as you are doing is never a good idea..
Better use PowerShells cmdlet Join-Path for that or .Net [System.IO.Path]::Combine() method.
As mklement0 already commented, Copy-Item by default does not procude any visual output unless you add -Verbose.
You can also append switch -PassThru and in that case, the cmdlet returns an object that represents the copied item.
In your case, why not add an informative message yourself, something like:
$SourceDir = 'C:\Dir1\Test\Files'
$DestDir = 'C:\Dir1\Test'
Import-Csv -Path 'C:\Dir1\Test\FileList.csv' | ForEach-Object {
# construct the source path
$Source = Join-Path -Path $SourceDir -ChildPath $_.FilePath
if (Test-Path -Path $source -PathType Leaf) {
# construct the destination path
$Dest = Join-Path -Path $DestDir -ChildPath $_.'Folder Ref'
# make sure the target path exists before trying to copy to it
$null = New-Item -Path $Dest -ItemType Directory -Force
# now copy the file
Write-Host "Copying file '$Source' to '$Dest'"
Copy-Item -Path $Source -Destination $Dest
}
else {
Write-Warning "File '$Source' could not be found"
}
}
I am in need of some assistance, I am new to PowerShell and am trying to use it to make some of my work easier. I am writing a PowerShell script to copy JPG files from one location (C:\Pictures\People\People) and moving them to a new location.
The issue is that in this new location I need to create a folder with the same name as the JPG and then another subfolder with the same name again as the JPG.
So I need to move images from C:\Pictures\People\People which I will call JPG_Image to C:\Pictures\JPG_Name\JPG_Name\'JPG_Image'
So far I found and have been working with this:
$SourceFolder = "C:\Pictures\People\People"
$TargetFolder = "C:\Pictures\"
# Find all files matching *.JPG in the folder specified
Get-ChildItem -Path $SourceFolder -Filter *.jpg |
ForEach-Object {
$ChildPath = Join-Path -Path $_.Name.Replace('.jpg','') -ChildPath $_.Name
[System.IO.FileInfo]$Destination = Join-Path -Path $TargetFolder -ChildPath $ChildPath
# Create the directory if it doesn't already exits
if( -not ( Test-Path -Path $Destination.Directory.FullName ) ){
New-Item -ItemType Directory -Path $Destination.Directory.FullName
}
Copy-Item -Path $_.FullName -Destination $Destination.FullName
}
You are making this harder on yourself than needs be.
Some enhancements to your code:
Add switch -File to the Get-ChildItem cmd so you do not also get DirectoryInfo objects
To get the filename without extension, there is a property .BaseName
Join-Path returns a string, no need to cast that into a [System.IO.FileInfo] object
If you add -Force to the New-Item cmd, there is no need to check if a folder already exists, because that will make the cmdlet either create a new folder or return the existing DirectoryInfo object.
Because we don't need that object (and the console output from it), we can just throw that away using $null = New-Item ...
Putting it all together:
$SourceFolder = "C:\Pictures\People\People"
$TargetFolder = "C:\Pictures"
# Find all files matching *.JPG in the folder specified
Get-ChildItem -Path $SourceFolder -Filter '*.jpg' -File |
ForEach-Object {
# Join-Path simply returns a string containing the combined path
# The BaseName property is the filename without extension
$ChildPath = Join-Path -Path $_.BaseName -ChildPath $_.BaseName
$Destination = Join-Path -Path $TargetFolder -ChildPath $ChildPath
# Create the directory if it doesn't already exits
# Using -Force will not give an error if the folder already exists
$null = New-Item -Path $Destination -ItemType Directory -Force
$_ | Copy-Item -Destination $Destination
}
Ok, looking for some assistance with Powershell. I need to create a subfolder with the same name in about 200 folders in a directory. So far I have this:
$folder = NewFolderName
new-item -type directory -path \\servername\directory\directory\$folder -Force
Will this work to create the single folder in all 200 folders?
Try the following code snippet:
$parent = '\\servername\directory'
$folder = 'NewFolderName'
Get-ChildItem -Path $parent -Directory |
ForEach-Object {
New-Item -WhatIf -Type Directory -Path (
Join-Path -Path $_.FullName -ChildPath $folder) -Force
}
Remove the risk mitigation parameter -WhatIf no sooner than debugged…
I want to create a folder, but I don't know how use a variable for define the path.
As is:
New-Item -ItemType directory -Path "C:\Users\tizio.caio\Desktop\BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
I want to replace C:\Users\tizio.caio\Desktop\ with a variable in order to make future reworks easier.
I would split the directory and filename, and use the environment variable USERPROFILE
$var = $env:USERPROFILE + "\Desktop\"
$backup = "BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
New-Item -ItemType directory -Path "$var$backup"
Assuming you always want the current users desktop, you can use the Environment.GetFolderPath() method to retrieve the path, then use the Join-Path cmdlet to combine it with the directory name:
$DesktopPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
$DirectoryName = "BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
$DirectoryPath = Join-Path $DesktopPath $DirectoryName
You could pack it into a function that takes a -Path parameter if you want to be able to override it:
function New-BackupDirectory
{
param(
[ValidateScript({Test-Path $_ -PathType Container})]
$Path = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
)
$DirectoryName = "BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
$DirectoryPath = Join-Path $Path $DirectoryName
mkdir $DirectoryPath
}
Depending how simple you want to go:
$folderpath = "C:\Users\tizio.caio\Desktop"
New-Item -ItemType directory -Path "$folderpath\BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
Or you can combine multiple variables:
$folderpath = "C:\Users\tizio.caio\Desktop"
$backuppath = "$folderpath\BACKUP_$((Get-Date).ToString('yyyyMMdd'))"
New-Item -ItemType directory -Path $backuppath
I'm trying to copy files from one location to another. I have a CSV that has the directory, name, and some other fields that aren't important for the move. I'm pretty sure that my code is trying to move the entire folder structure and not just the file. How can I just move the file? OR How can I move a similar folder structure to the new location (\folder\username)
The directory looks something like:
\\server\folder\username
The code I was trying:
Import-Csv c:\movefiles.csv | ForEach-Object {Copy-Item -LiteralPath ($_.Directory + "\" + $_.name) -Destination c:\}
The destination will actually be a location on another server.
The code your trying should copy the file(as long as the name property is the name of a file) and save it in c:\ just like you wanted. You might want to use Join-Path to combine the directory and filename instead of your current approach. It makes sure that you don't have multiple \ etc.. Ex:
ForEach-Object {Copy-Item -LiteralPath (Join-Path $_.Directory $_.name) -Destination c:\}
Copy with folderstructure(untested):
function MoveTo-NewServer {
param(
[Parameter(Mandatory=$true)]
$Csvpath,
[Parameter(Mandatory=$true)]
$Newserver)
if(Test-Path $Csvpath -PathType Leaf) {
Import-Csv $Csvpath | ForEach-Object {
$h = ([uri]$_.directory).Host
$src = Join-Path $_.Directory $_.name
$dest = $src.Replace($h, $Newserver)
if(!(Test-Path $dest)) { New-Item $dest -ItemType File -Force }
Copy-Item -LiteralPath $src -Destination $dest -Force
}
}
}
As said, this is untested. Try to use it like this:
MoveTo-NewServer -Csvpath "c:\mycsv.csv" -Newserver "server2"