alexianit
asked on
How to us a powershell script to copy
I am still a novice when it comes to scripting & am trying to learn as I go.
I'm not certain if powershell will do what I want it to, but I am hoping someone with more know-how could provide me with the PS code to do the following.
I wish the script to create a directory, at the end of a path, with a unique name, say... today's date.
Copy files of multiple types from one directory into this JUST MADE directory, such as all *.xls & *.doc type files.
An additional problem I seem to be running up against is that PS is in restricted mode, which I know that this is not something you'd simply want to disable, but I don't quite yet understand how to sign a script so that it'll run.
Also, can PS scripts be run via a scheduled task?
I'm not certain if powershell will do what I want it to, but I am hoping someone with more know-how could provide me with the PS code to do the following.
I wish the script to create a directory, at the end of a path, with a unique name, say... today's date.
Copy files of multiple types from one directory into this JUST MADE directory, such as all *.xls & *.doc type files.
An additional problem I seem to be running up against is that PS is in restricted mode, which I know that this is not something you'd simply want to disable, but I don't quite yet understand how to sign a script so that it'll run.
Also, can PS scripts be run via a scheduled task?
And then this bit :)
> I wish the script to create a directory, at the end of a path, with a unique name, say... today's date.
> Copy files of multiple types from one directory into this JUST MADE directory, such as all *.xls & *.doc type files.
Okay... no problem. How would you like the Directory to appear?
Perhaps for the directory:
$Directory = mkdir "SomeDirectory-$((Get-Date
mkdir is an alias for "New-Item <Path> -Type Directory" rather than it being the DOS command.
Then for the copy part...
Copy-Item *.xls, *.doc $Directory.FullName
Are the files spread around a number of source folders?
Chris
ASKER
Here's an example of what I want:
All files reside in a single directory
Source: \\ServernameA\Program Files\Dir01\subdir\*.txt
copy to: \\ServernameB\Public\Dir02 \timestamp \*.txt
or maybe:
Source: C:\Program Files\Dir01\subdir\*.txt
copy to: \\ServernameB\Public\Dir02 \timestamp \*.txt
& would the target machine need PS installed? Its an embedded NAS box, although the destination could be altered to a different box.
All files reside in a single directory
Source: \\ServernameA\Program Files\Dir01\subdir\*.txt
copy to: \\ServernameB\Public\Dir02
or maybe:
Source: C:\Program Files\Dir01\subdir\*.txt
copy to: \\ServernameB\Public\Dir02
& would the target machine need PS installed? Its an embedded NAS box, although the destination could be altered to a different box.
ASKER
the directory name should really only be the date
ASKER
Taking a closer look at this sourcedirectory of mine I am noticing there is quite a diverse range of file types, including some with no extension. Its a programs data directory that we are attempting a simple, copy backup of.
Would it be better to simply use *.* rather than *.doc etc... ? & will that get the files without an extension?
Would it be better to simply use *.* rather than *.doc etc... ? & will that get the files without an extension?
> would the target machine need PS installed?
No. Only the system running the script.
We need to identify the steps for this. First one is to create the date-stamped directory.
$Directory = New-Item -Name $((Get-Date).ToString('dd.
We can change how the time stamp is formatted, I made that one up, it's not a fixed name.
Once we have the directory we need a way to identify which files are interesting. In the example above, I'd done that with Copy-Item's acceptance of wild-cards. We can use Get-ChildItem to introduce greater flexibility if that doesn't give enough.
Finally, having identified the files they need copying to the newly created directly. The step was combined with the previous for simplicity. So you could do:
$SourceDir = "\\ServernameA\Program Files\Dir01\subdir\"
Copy-Item "$SourceDir\*.txt", "$SourceDir\*.doc" -Destination $Directory.FullName
As long as you can split a process up into small steps you can script it.
Chris
> Would it be better to simply use *.* rather than *.doc etc... ? & will that get the files without an extension?
Using *.* will show all files that contain a dot. You'd be better leaving it at * to capture everything.
Are you wanting to capture files created / modified on a particular day for the copy? Or just everything?
Chris
ASKER
leave it to me to complicate things ...
Only the files within the directory, not the subfolders or their chiildren
Only the files within the directory, not the subfolders or their chiildren
We might be better with Where-Object then, greater flexibility. Give this a try?
$SourceDir = "\\ServernameA\Program Files\Dir01\subdir\"
Get-ChildItem "$SourceDir\*" | `
Where-Object{ $_.PsIsContainer -eq $False } | `
Copy-Item $_.FullName -Destination $Directory.FullName
Chris
ASKER
Ok, to verify ... this is basically what I have so far.
I've modified the paths to reflect a little closer to what I have. I haven't tested yet, but this should yield the desired results?
I've modified the paths to reflect a little closer to what I have. I haven't tested yet, but this should yield the desired results?
$Directory = New-Item -Name $((Get-Date).ToString('dd.MM.yyyy')) -Type Directory -Path "\\NASBOX\Public\program data backup\"
$SourceDir = "\\Server\Program Files\Appname\Programs\data\"
Get-ChildItem "$SourceDir\*" | `
Where-Object{ $_.PsIsContainer -eq $False } | `
Copy-Item $_.FullName -Destination $Directory.FullName
We need to lose the final "\" from SourceDir, or drop the \ we add in Get-ChildItem (I've done that below).
PowerShell has a -WhatIf parameter that allows a bit of a different level of testing. Lets have that in while testing (we only need it for the Copy-Item command).
Chris
$Directory = New-Item -Name $((Get-Date).ToString('dd.MM.yyyy')) -Type Directory -Path "\\NASBOX\Public\program data backup\"
$SourceDir = "\\Server\Program Files\Appname\Programs\data\"
Get-ChildItem "$SourceDir*" | `
Where-Object{ $_.PsIsContainer -eq $False } | `
Copy-Item $_.FullName -Destination $Directory.FullName -WhatIf
ASKER
I get the following error:
Copy-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\test.ps1:6 char:12
+ Copy-Item <<<< $_.FullName -Destination $Directory.FullName -WhatIf
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidation Exception
+ FullyQualifiedErrorId : ParameterArgumentValidatio nErrorNull NotAllowed ,Microsoft .PowerShel l.Commands .CopyItemC ommand
Copy-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\test.ps1:6 char:12
+ Copy-Item <<<< $_.FullName -Destination $Directory.FullName -WhatIf
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidation
+ FullyQualifiedErrorId : ParameterArgumentValidatio
ASKER
however the directory is being created as desired
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
OK looks good.
I ran this in Powershell_ISE.exe and from what I can tell the test results look excellent.
now I need to remove the -whatif parmater, do I just delete '-whatif' ?
I ran this in Powershell_ISE.exe and from what I can tell the test results look excellent.
now I need to remove the -whatif parmater, do I just delete '-whatif' ?
Yep, that's right :)
Chris
ASKER
Thank you very much ... most excellent!
ASKER
One last bit. The script is great. You mentioned earlier to feed the scheduled task something like this:
PowerShell.exe Script1.ps1
should it rather be:
C:\WINDOWS\system32\WINDOW ~2\v1.0\PO WERS~1.EXE C:\Script1.ps1
Its just that when I set up the task it asks what program to run, perhaps I should only reference the script and not the Powershell.exe?
PowerShell.exe Script1.ps1
should it rather be:
C:\WINDOWS\system32\WINDOW
Its just that when I set up the task it asks what program to run, perhaps I should only reference the script and not the Powershell.exe?
PowerShell.exe is (or should be) in the system path so shouldn't need all of that :)
You can't actually execute PowerShell scripts without telling it to use PowerShell.exe first (either by double-clicking or just using the script name), a design choice by MS at the outset, I guess they didn't want to encourage abuse of yet another windows scripting language.
Chris
You'd need a code-signing certificate, I could never justify the cost. Unless you're troubled by it I advise changing the ExecutionPolicy to RemoteSigned, with:
Set-ExecutionPolicy RemoteSigned
That means that remotely executed scripts will require signing, locally executed will be fine.
And yes, they can be run as scheduled tasks. For example, feed the scheduled task a command like this:
PowerShell.exe Script1.ps1
You can also execute PowerShell Commands directly, or pass in arguments, it all depends on what you need.
Chris