PowerShell copy-item - powershell

I am trying to copy latest 30days files to the folder by this code:
$month = (get-date).AddDays(-30).ToString("yyyMM")
$lastmonthfiles = Write-Host (-join('DCP_', $month,"*.csv"))
Copy-Item -Path Write-Host (-join ("C:\DC+\History\", $lastmonthfiles)) -Destination C:\DC+\History\Backup
but I am having a problem in path in copy-item instruction, which is
Copy-Item : A positional parameter cannot be found that accepts argument 'C:\DC+\History\'.
At line:5 char:1
+ Copy-Item -Path Write-Host (-join ("C:\DC+\History\", $lastmonthfiles ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Copy-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
I am new in PowerShell, and programming so, I could not understand, how can I update and achieve a goal.

Try this:
$Source = Get-Item "C:\Games"
$Destination = "E:\Backup"
$LogFile = "C:\Copy-LogFile.txt"
Copy-Item -Path $( $Source | Where LastWriteTime -LE (Get-Date).AddDays(-30) ) -Destination $Destination -Recurse -PassThru |
Out-File $LogFile -Force
This takes care of your copy function and generates an output log.

Sorry, but your code makes no sense to me...
If it is your aim to copy files to a subfolder in a backup path, try this:
# get the date to use as subfolder to copy to and also to filter the last 30 days files
$refDate = (Get-Date).AddDays(-30).Date # .Date sets it to midnight
# set this variable to the folder where the csv are to be found
$sourceFolder = 'X:\Path\To\Where\The\Files\Are'
# create a destination path to copy to (just a string)
$destination = Join-Path -Path 'C:\DC+\History\Backup' -ChildPath ($refDate.ToString("yyyMM"))
# create this destination folder
$null = New-Item -Path $destination -ItemType Directory -Force
# get the files and copy them to the destination folder
Get-ChildItem -Path $sourceFolder -Filter '*.csv' -File | # filter on CSV fies only
Where-Object { $_.LastWriteTime -ge $refDate } | # filter on date 'last 30 days'
Copy-Item -Destination $destination -Force

Related

Move Item path null

I have to move files from a folder corresponding to a CSV column like that :
id
name
1a
file1
2b
file2
3c
file3
4d
file4
So if in my folder I have a file named file1 I need to create a folder named 1a and put file1 inside.
I have the following script
$CsvId = Import-Csv './test.csv'
$sourcePath= "C:\Users\olong\Desktop\object"
$dirPath = "C:\Users\olong\Desktop\dir"
$files = Get-ChildItem -Path $sourcePath | ForEach-Object -Process {[System.IO.Path]::GetFileNameWithoutExtension($_)}
$pattern = '(?<=_).*(?=_)'
ForEach ($item In $CsvId) {
$objectID = $item.'id'
$docID = $item.'name'
$location = $dirPath+ "\" + $objectID
Foreach ($file in $files) {
if($file -contains $docID) {
if (-not (Test-Path -Path $location)) {
mkdir -Path $location
}
Move-Item ($file.FullName) -Destination $location -Verbose -Force
}
}
}
But it gives me that error :
Move-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\Users\olong\Desktop\scriptMove.ps1:19 char:15
+ Move-Item ($file.FullName) -Destination $location -Verbose -Force
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Move-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.MoveItemCommand
With PowerShell's debugger $file is not null and with or without parenthesis on $file.FullName does nothing
I think what you want to do is to get the file(s) as mentioned in the csv under header 'name' having any extension into a subfolder as mentioned in field 'id' and create that subfolder first if it does not already exist.
If my assumtion is correct, you can try below:
$sourcePath = "C:\Users\olong\Desktop\object"
$destinationPath = "C:\Users\olong\Desktop\dir"
Import-Csv -Path './test.csv' | ForEach-Object {
$targetDirectory = Join-Path -Path $destinationPath -ChildPath $_.id
# create the output subfolder if it does not already exist
$null = New-Item -Path $targetDirectory -ItemType Directory -Force
# next use the file basename from the $_.name column as filter and move the file(s)
Get-ChildItem -Path $sourcePath -Filter "$($_.name).*" -File | Move-Item -Destination $targetDirectory
}

Export Variable contents to file

I have contents in a variable from GitHub and I want to export then to file automatically created o my local machine
I have tried to use
$FileContent | Out-File ('C:\Devjobs\clonefolder' + '\' + $repo.name + '\' + $srccontent.name)
It gives the error
Out-File : Could not find a part of the path 'C:\Devjobs\clonefolder\bct-common-devcomm-codegen-messages\BCT.Common.DevComm.CodeGen.Messages.sln'.
At line:1 char:18
+ ... lnContent | Out-File ('C:\Devjobs\clonefolder' + '\' + $repo.name + ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (:) [Out-File], DirectoryNotFoundException
+ FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand
As stackprotector already commented, the error shows DirectoryNotFoundException, which means you are trying to create a file in a directory that does not yet exist.
To avoid that, first create the path for the output file, then create the file.
$pathOut = Join-Path -Path 'C:\Devjobs\clonefolder' -ChildPath $repo.name
# create the folder path if it does not exist already
$null = New-Item -Path $pathOut -ItemType Directory -Force
# now write the file
$FileContent | Set-Content -Path (Join-Path -Path $pathOut -ChildPath $srccontent.name)
By using the -Force switch on New-Item you will either create the directory, OR have a DirectoryInfo object returned if the folder already existed.
In this case, we have no further need for that object, so we discard it with $null =.
Beware that this only works like that on the file system, if you would do the same on a registry key, you wil lose all content of the existing key!
Note: I use Set-Content rather than Out-File because on PowerShell versions up to and including 5.1, Out-File without using the -Encoding parameter will write the file in Unicode (UTF16-LE) encoding which may or may not be what you expect.
Following your comment:
foreach ($srccontent in $srccontents) {
if (<cond>) {
$slnContent = <rest>
$NewslnContent = "content"
$pathOut = Join-Path -Path 'C:\Devjobs\clonefolder' -ChildPath $repo.name
# first create the folder path if it does not exist already
$null = New-Item -Path $pathOut -ItemType Directory -Force
# now write the file
$NewslnContent | Set-Content -Path (Join-Path -Path $pathOut -ChildPath $srccontent.name)
}
}
Instead of string concatenation you may want to try Join-Path for cross-platform. That being said, if you are on a Windows machine this is not likely to be your issue.
You may want to use Test-Path to verify if the path and the file exists already.
$path = 'C:' |
Join-Path -ChildPath 'Devjobs' |
Join-Path -ChildPath 'clonefolder' |
Join-Path -ChildPath $repo.name
$filepath = $path | Join-Path -ChildPath $srccontent.name
If (-Not (Test-Path $path)) {
New-Item -Type Directory -Path $path
}
If (-Not (Test-Path $filepath)) {
Remove-Item -Path $filepath
}
$FileContent | Out-File $filepath

Powershell | Rename file with random name

I'm making a script to rename a specific file with a random name. But when running, the following error always occurs:
It is not possible to convert the value ".jpg" to the type "System.Int32". Error: "The input string was not in the correct format."
In C:\Windows\system32\WindowsPowerShell\v1.0\Modules\SetDiscordWallpaper\SetDiscordWallpaper.ps1:7 character:7
+ Rename-Item -Path $file.FullName -NewName ($random + $file.Exte ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
Here is the code I am using
function Set-DiscordWallpaper {
$path = "C:\Windows\Temp\*"
foreach($file in $(Get-ChildItem -Path $path -Include "Wallpaper.jpg")) {
$extension = [System.IO.Path]::GetExtension($file.FullName);
$randomName = [System.IO.Path]::ChangeExtension([System.IO.Path]::GetRandomFileName(), $extension)
$newPath = "C:\inetpub\wwwroot\"
Write-Host "Changing File $($file.Name) to $randomName"
Move-Item -Path $file.FullName -Destination $newPath
}
}
I ask you to help me please. I'm waiting the answer. Thanks
The code (second part in your question) creates the new random filename just fine, only the line Move-Item -Path $file.FullName -Destination $newPath does nothing with that new name and moves the file with its original name to the new path.
Change that line to
Move-Item -Path $file.FullName -Destination (Join-Path -Path $newPath -ChildPath $randomName)
so the file gets moved with the random name in the new path.
Or is your intention to copy the file to its new destination keeping the original filename there and after that rename the original?
In that case do:
Write-Host "Changing File $($file.Name) to $randomName"
Copy-Item -Path $file.FullName -Destination $newPath # copy with original name
$file | Rename-Item -NewName $randomName # rename the original file

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.
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.

Error message in script

I am trying to script a solution copying some files from one location to another..
I have a list of files in a .csv format, with headers
"ParentFolder, Name, FullName, lastwritetime."
Content of file is, which has hundreds of lines, and different paths, but same drive letter:
"X:\clients\A90\201AA3.05\","2012.08 RAP Proposal.xlsm","X:\clients\A90\201AA3.05\2012.08 RAP Proposal.xlsm","20/05/2016 10:41:08"
What i would like to do is copy the above..
"X:\clients\A90\201AA3.05\2012.08 RAP Proposal.xlsm" to a new location with differnet drive, but same directory structure. So in the csv file i have the filename and path, but am unsure how to split the drive from there and make a variable.
I have a foreach loop..
$ToCopy = Import-Csv "c:\temp\log.csv"
foreach($Line in $ToCopy)
{
$FullPath = $Line.ParentFolder
$File = $Line.Name
$FullName = $Line.FullName
$file = "$FullPath\$FullName"
$DestPath = Split-Path $FullPath -NoQualifier
Copy-Item "$FullName" -Destination c:\test\$DestPath
}
Error message that i am getting is :
+ CategoryInfo : NotSpecified: (:) [Copy-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : System.IO.DirectoryNotFoundException,Microsoft.PowerShell.Commands.CopyItemCommand
Copy-Item : Could not find a part of the path 'C:\test\clients\A90\Support\_index0901\'.
At line:9 char:9
+ Copy-Item "$FullName" -Destination c:\test\$DestPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : System.IO.DirectoryNotFoundException,Microsoft.PowerShell.Commands.CopyItemCommand
You get the error because the directory structure of your target path probably does not exist
To solve that you can create a 'temporary' file with New-Item ... -Force which creates the missing directories if necessary and then overwrite that file with Copy-Item like so
$ToCopy = Import-Csv "c:\temp\log.csv"
foreach($Line in $ToCopy)
{
$FullPath = $Line.ParentFolder
$File = $Line.Name
$FullName = $Line.FullName
$file = "$FullPath\$FullName"
$DestPath = Split-Path $FullPath -NoQualifier
$DestFile = c:\test\$DestPath
New-Item -ItemType File -Force $DestFile
Copy-Item "$FullName" -Destination $DestFile -Force
}
You need to create the folders before attempting to copy files in them.
Here's a way to do it, simplified from what you have, but with an added line to take care of the folders' creation.
foreach($File in $ToCopy)
{
$DestPath = Join-Path -Path 'c:\test' -ChildPath ( Split-Path $File.ParentFolder -NoQualifier )
If ( -not ( Test-Path -Path $DestPath ) ) { New-Item -Path $DestPath -Force -ItemType Directory }
Copy-Item $File.FullName -Destination $DestPath -WhatIf
}
(Be careful, I change the iteration variable from $Line to $File)
You are trying to copy files into c:\test\ directory which does not exist. Create this directory before loop:
mkdir c:\test\
or, in case directory may exist
mkdir c:\test\ -Force