How to move folders from one location to another using PowerShell
So i have a directory full of folders that i want to move to another area, also i only want to move the folders that were created 30 days ago or more. I have a script that does what i need for files but it doesnt seem to work for folders. Script is below
Script for moving files
param (
[Parameter(Mandatory=$true)][string]$destinationRoot
)
$path = (Get-Item -Path ".").FullName
Get-ChildItem -Recurse | ?{ $_.PSIsContainer }
Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} |
Foreach-Object {
$content = $path + "" + $_.Name
$year = (Get-Item $content).LastWriteTime.year.ToString()
$monthNumber = (Get-Item $content).LastWriteTime.month
$month = (Get-Culture).DateTimeFormat.GetMonthName($monthNumber)
$destination = $destinationRoot + "" + $year + "" + $month
New-Item -ItemType Directory -Force -Path $destination
Move-Item -Path $content -Destination $destination -force
}
The Get-ChildItem portion does not seem to pull directories in like it should.
powershell
|
show 8 more comments
So i have a directory full of folders that i want to move to another area, also i only want to move the folders that were created 30 days ago or more. I have a script that does what i need for files but it doesnt seem to work for folders. Script is below
Script for moving files
param (
[Parameter(Mandatory=$true)][string]$destinationRoot
)
$path = (Get-Item -Path ".").FullName
Get-ChildItem -Recurse | ?{ $_.PSIsContainer }
Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} |
Foreach-Object {
$content = $path + "" + $_.Name
$year = (Get-Item $content).LastWriteTime.year.ToString()
$monthNumber = (Get-Item $content).LastWriteTime.month
$month = (Get-Culture).DateTimeFormat.GetMonthName($monthNumber)
$destination = $destinationRoot + "" + $year + "" + $month
New-Item -ItemType Directory -Force -Path $destination
Move-Item -Path $content -Destination $destination -force
}
The Get-ChildItem portion does not seem to pull directories in like it should.
powershell
1
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
1
just useGet-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite
– ArcSet
Nov 12 at 15:18
1
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
1
@mklement0 I think there is a flaw with gci recursing and in the foreach combining$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.
– LotPings
Nov 12 at 15:33
|
show 8 more comments
So i have a directory full of folders that i want to move to another area, also i only want to move the folders that were created 30 days ago or more. I have a script that does what i need for files but it doesnt seem to work for folders. Script is below
Script for moving files
param (
[Parameter(Mandatory=$true)][string]$destinationRoot
)
$path = (Get-Item -Path ".").FullName
Get-ChildItem -Recurse | ?{ $_.PSIsContainer }
Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} |
Foreach-Object {
$content = $path + "" + $_.Name
$year = (Get-Item $content).LastWriteTime.year.ToString()
$monthNumber = (Get-Item $content).LastWriteTime.month
$month = (Get-Culture).DateTimeFormat.GetMonthName($monthNumber)
$destination = $destinationRoot + "" + $year + "" + $month
New-Item -ItemType Directory -Force -Path $destination
Move-Item -Path $content -Destination $destination -force
}
The Get-ChildItem portion does not seem to pull directories in like it should.
powershell
So i have a directory full of folders that i want to move to another area, also i only want to move the folders that were created 30 days ago or more. I have a script that does what i need for files but it doesnt seem to work for folders. Script is below
Script for moving files
param (
[Parameter(Mandatory=$true)][string]$destinationRoot
)
$path = (Get-Item -Path ".").FullName
Get-ChildItem -Recurse | ?{ $_.PSIsContainer }
Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} |
Foreach-Object {
$content = $path + "" + $_.Name
$year = (Get-Item $content).LastWriteTime.year.ToString()
$monthNumber = (Get-Item $content).LastWriteTime.month
$month = (Get-Culture).DateTimeFormat.GetMonthName($monthNumber)
$destination = $destinationRoot + "" + $year + "" + $month
New-Item -ItemType Directory -Force -Path $destination
Move-Item -Path $content -Destination $destination -force
}
The Get-ChildItem portion does not seem to pull directories in like it should.
powershell
powershell
edited Nov 12 at 15:29
asked Nov 12 at 14:56
Philip Loyer
3961317
3961317
1
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
1
just useGet-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite
– ArcSet
Nov 12 at 15:18
1
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
1
@mklement0 I think there is a flaw with gci recursing and in the foreach combining$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.
– LotPings
Nov 12 at 15:33
|
show 8 more comments
1
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
1
just useGet-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite
– ArcSet
Nov 12 at 15:18
1
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
1
@mklement0 I think there is a flaw with gci recursing and in the foreach combining$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.
– LotPings
Nov 12 at 15:33
1
1
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
1
1
just use
Get-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite– ArcSet
Nov 12 at 15:18
just use
Get-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite– ArcSet
Nov 12 at 15:18
1
1
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
1
1
@mklement0 I think there is a flaw with gci recursing and in the foreach combining
$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.– LotPings
Nov 12 at 15:33
@mklement0 I think there is a flaw with gci recursing and in the foreach combining
$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.– LotPings
Nov 12 at 15:33
|
show 8 more comments
1 Answer
1
active
oldest
votes
So looking at the script i decided to change some things up
Function Move-FilesByAge(){
param (
[Parameter(Mandatory=$true)][string]$Source,
[Parameter(Mandatory=$true)][string]$Destination,
[Parameter(Mandatory=$true)][timespan]$AgeLimit
)
Get-ChildItem $Source -Directory -Recurse | ?{
$($_.CreationTimeUtc.Add($AgeLimit)) -lt $((Get-Date).ToUniversalTime())
} | %{
$Dpath = $Destination + "" + $_.CreationTimeUtc.ToString("yyyy") + "" + $_.CreationTimeUtc.ToString("MMMM")
New-Item -ItemType Directory -Force -Path $Dpath
Move-Item $_ -Destination $Dpath -Force
}
}
Move-FilesByAge -Source C:Test -Destination C:Test2 -AgeLimit (New-TimeSpan -days 30)
This can lead to a major issue. If a folder with the same name exists then it will pop a error that folder exists.
Since you are new to powershell lets go over some basics about this script. In Powershell we love Piping |
which you did well in the original. We also a big fan of aliases Where-Object ?{}
, Foreach-Object %{}
.
Get-ChildItem has a built in switch for just returning directories -directory
.
You are also using last LastWriteTime when you should be using CreationTime. CreationTimeUtc allows you to standardize your time across timezones by providing a base timezone.
Date.ToString(Date Format Here). IS a great way to shorten how you parse the date as a string. .ToString("yyyy")
gets you the year in 4 numbers like 2018. .ToString("MMMM")
will get the month by name like March.
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the-format
operator:$Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string` which has a meaning it needs to be escaped
`.
– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264748%2fhow-to-move-folders-from-one-location-to-another-using-powershell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
So looking at the script i decided to change some things up
Function Move-FilesByAge(){
param (
[Parameter(Mandatory=$true)][string]$Source,
[Parameter(Mandatory=$true)][string]$Destination,
[Parameter(Mandatory=$true)][timespan]$AgeLimit
)
Get-ChildItem $Source -Directory -Recurse | ?{
$($_.CreationTimeUtc.Add($AgeLimit)) -lt $((Get-Date).ToUniversalTime())
} | %{
$Dpath = $Destination + "" + $_.CreationTimeUtc.ToString("yyyy") + "" + $_.CreationTimeUtc.ToString("MMMM")
New-Item -ItemType Directory -Force -Path $Dpath
Move-Item $_ -Destination $Dpath -Force
}
}
Move-FilesByAge -Source C:Test -Destination C:Test2 -AgeLimit (New-TimeSpan -days 30)
This can lead to a major issue. If a folder with the same name exists then it will pop a error that folder exists.
Since you are new to powershell lets go over some basics about this script. In Powershell we love Piping |
which you did well in the original. We also a big fan of aliases Where-Object ?{}
, Foreach-Object %{}
.
Get-ChildItem has a built in switch for just returning directories -directory
.
You are also using last LastWriteTime when you should be using CreationTime. CreationTimeUtc allows you to standardize your time across timezones by providing a base timezone.
Date.ToString(Date Format Here). IS a great way to shorten how you parse the date as a string. .ToString("yyyy")
gets you the year in 4 numbers like 2018. .ToString("MMMM")
will get the month by name like March.
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the-format
operator:$Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string` which has a meaning it needs to be escaped
`.
– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
add a comment |
So looking at the script i decided to change some things up
Function Move-FilesByAge(){
param (
[Parameter(Mandatory=$true)][string]$Source,
[Parameter(Mandatory=$true)][string]$Destination,
[Parameter(Mandatory=$true)][timespan]$AgeLimit
)
Get-ChildItem $Source -Directory -Recurse | ?{
$($_.CreationTimeUtc.Add($AgeLimit)) -lt $((Get-Date).ToUniversalTime())
} | %{
$Dpath = $Destination + "" + $_.CreationTimeUtc.ToString("yyyy") + "" + $_.CreationTimeUtc.ToString("MMMM")
New-Item -ItemType Directory -Force -Path $Dpath
Move-Item $_ -Destination $Dpath -Force
}
}
Move-FilesByAge -Source C:Test -Destination C:Test2 -AgeLimit (New-TimeSpan -days 30)
This can lead to a major issue. If a folder with the same name exists then it will pop a error that folder exists.
Since you are new to powershell lets go over some basics about this script. In Powershell we love Piping |
which you did well in the original. We also a big fan of aliases Where-Object ?{}
, Foreach-Object %{}
.
Get-ChildItem has a built in switch for just returning directories -directory
.
You are also using last LastWriteTime when you should be using CreationTime. CreationTimeUtc allows you to standardize your time across timezones by providing a base timezone.
Date.ToString(Date Format Here). IS a great way to shorten how you parse the date as a string. .ToString("yyyy")
gets you the year in 4 numbers like 2018. .ToString("MMMM")
will get the month by name like March.
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the-format
operator:$Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string` which has a meaning it needs to be escaped
`.
– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
add a comment |
So looking at the script i decided to change some things up
Function Move-FilesByAge(){
param (
[Parameter(Mandatory=$true)][string]$Source,
[Parameter(Mandatory=$true)][string]$Destination,
[Parameter(Mandatory=$true)][timespan]$AgeLimit
)
Get-ChildItem $Source -Directory -Recurse | ?{
$($_.CreationTimeUtc.Add($AgeLimit)) -lt $((Get-Date).ToUniversalTime())
} | %{
$Dpath = $Destination + "" + $_.CreationTimeUtc.ToString("yyyy") + "" + $_.CreationTimeUtc.ToString("MMMM")
New-Item -ItemType Directory -Force -Path $Dpath
Move-Item $_ -Destination $Dpath -Force
}
}
Move-FilesByAge -Source C:Test -Destination C:Test2 -AgeLimit (New-TimeSpan -days 30)
This can lead to a major issue. If a folder with the same name exists then it will pop a error that folder exists.
Since you are new to powershell lets go over some basics about this script. In Powershell we love Piping |
which you did well in the original. We also a big fan of aliases Where-Object ?{}
, Foreach-Object %{}
.
Get-ChildItem has a built in switch for just returning directories -directory
.
You are also using last LastWriteTime when you should be using CreationTime. CreationTimeUtc allows you to standardize your time across timezones by providing a base timezone.
Date.ToString(Date Format Here). IS a great way to shorten how you parse the date as a string. .ToString("yyyy")
gets you the year in 4 numbers like 2018. .ToString("MMMM")
will get the month by name like March.
So looking at the script i decided to change some things up
Function Move-FilesByAge(){
param (
[Parameter(Mandatory=$true)][string]$Source,
[Parameter(Mandatory=$true)][string]$Destination,
[Parameter(Mandatory=$true)][timespan]$AgeLimit
)
Get-ChildItem $Source -Directory -Recurse | ?{
$($_.CreationTimeUtc.Add($AgeLimit)) -lt $((Get-Date).ToUniversalTime())
} | %{
$Dpath = $Destination + "" + $_.CreationTimeUtc.ToString("yyyy") + "" + $_.CreationTimeUtc.ToString("MMMM")
New-Item -ItemType Directory -Force -Path $Dpath
Move-Item $_ -Destination $Dpath -Force
}
}
Move-FilesByAge -Source C:Test -Destination C:Test2 -AgeLimit (New-TimeSpan -days 30)
This can lead to a major issue. If a folder with the same name exists then it will pop a error that folder exists.
Since you are new to powershell lets go over some basics about this script. In Powershell we love Piping |
which you did well in the original. We also a big fan of aliases Where-Object ?{}
, Foreach-Object %{}
.
Get-ChildItem has a built in switch for just returning directories -directory
.
You are also using last LastWriteTime when you should be using CreationTime. CreationTimeUtc allows you to standardize your time across timezones by providing a base timezone.
Date.ToString(Date Format Here). IS a great way to shorten how you parse the date as a string. .ToString("yyyy")
gets you the year in 4 numbers like 2018. .ToString("MMMM")
will get the month by name like March.
edited Nov 12 at 15:56
answered Nov 12 at 15:47
ArcSet
3,0581925
3,0581925
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the-format
operator:$Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string` which has a meaning it needs to be escaped
`.
– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
add a comment |
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the-format
operator:$Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string` which has a meaning it needs to be escaped
`.
– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
Worked like a charm, thanks so much for your help
– Philip Loyer
Nov 12 at 16:12
You could simplify things with the
-format
operator: $Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string ` which has a meaning it needs to be escaped
`.– LotPings
Nov 12 at 16:12
You could simplify things with the
-format
operator: $Dpath = "{0}{1:yyyy\MMMM}" -f $Destination,$_.CreationTimeUtc
to include a literal character in a format string ` which has a meaning it needs to be escaped
`.– LotPings
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
good point @LotPings
– ArcSet
Nov 12 at 16:12
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
Hmm backticks and backslashes don't play together nicely in a comment: To include a literal character in a format string which has a meaning it needs to be escaped \
– LotPings
Nov 12 at 16:16
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264748%2fhow-to-move-folders-from-one-location-to-another-using-powershell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Please update your question to describe what, specifically, doesn't work.
– mklement0
Nov 12 at 15:09
what if a file thats less then 30 days is in a folder that is greater then 30 days?
– ArcSet
Nov 12 at 15:14
1
just use
Get-ChildItem -Directory -Recurse
. Honestly there are quite a few things that would make this script better. Let me see if i cant do a fast rewrite– ArcSet
Nov 12 at 15:18
1
@mklement0 apologies for the name misspell. Was not intentional
– Philip Loyer
Nov 12 at 15:30
1
@mklement0 I think there is a flaw with gci recursing and in the foreach combining
$path
with the current name without taking into account that the current item might be a (sub-)subdir of $path - so $content points to a non existing folder.– LotPings
Nov 12 at 15:33