Link to home
Start Free TrialLog in
Avatar of alexianit
alexianitFlag for United States of America

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?
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image


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

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).ToString('dd.MM.yyyy'))"

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
Avatar of alexianit

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.
the directory name should really only be the date
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 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.MM.yyyy')) -Type Directory -Path "\\ServernameB\Public\Dir02\"

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
leave it to me to complicate things  ...
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
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?


$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

Open in new window


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

Open in new window

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], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand
however the directory is being created as desired
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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' ?

Yep, that's right :)

Chris
Thank you very much ... most excellent!
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\POWERS~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 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