How to transfer files (folders) from one server to another with PowerShell? - powershell

I just started working with PowerShell and I want to know how to transfer files between a local server and a remote server.
Currently I do not have Administrator access to either server (I know I'm going to need it), how do I target the Get cmdlt? Do I use a URL?

It's vital that you get up to speed on the topic. Take the time to jump over to MS Virtual academy
or MS Channel9
or YouTube and take a quick training course on the topic.
What you are asking for is covered in them as well as in the PowerShell Help files, which include examples on how to do this.
# get function / cmdlet details
(Get-Command -Name Copy-Item).Parameters
Get-help -Name Copy-Item -Full
Get-help -Name Copy-Item -Online
Get-help -Name Copy-Item -Examples
NAME
Copy-Item
SYNOPSIS
Copies an item from one location to another.
Example 1: Copy a file to the specified directory
PS C:\>Copy-Item "C:\Wabash\Logfiles\mar1604.log.txt" -Destination "C:\Presentation"
This command copies the mar1604.log.txt file to the C:\Presentation directory. The command does not delete the original
file.
Example 2: Copy the contents of a directory to another directory
PS C:\>Copy-Item "C:\Logfiles" -Destination "C:\Drawings" -Recurse
This command copies the entire contents of the Logfiles directory into the Drawings directory. If the LogFiles directory contains files
in
subdirectories, those subdirectories will be copied with their file trees intact. The Container parameter is set to true by default.
This preserves
# Get parameter that accepts pipeline input
Get-Help Copy-Item -Parameter * |
Where-Object {$_.pipelineInput -match 'true'} |
Select *
# Get cmdlet / function parameter aliases
(Get-Command Copy-Item).Parameters.Values |
where aliases |
select Name, Aliases | Out-GridView -PassThru -Title 'Alias results for a given cmdlet or function.'

Related

Bulk Transfer of Subfolders into Parent Folders

I have a problem that I cannot seem to find any solution to online. I am trying to restructure some data structures that I ended up with after exporting some data from my old database service.
The export left me with a bunch of client folders in the format of [Client Name] -> Archive -> Archive -> [Client Files/Subfolders]. What I would like to end up with is [Client Name] -> [Client Files/Subfolders], removing the two redundant "Archive" folders in between.
Many people have suggested to me that I simply cut and paste the files from the subfolder to the client root directory, however with hundreds of client folders this would be a very long task to do. Would there be any batch cmd command or powershell command I could use to work through these folders and restructure them? Any advice is much appreciated.
Three built-in PoSH cmdlets are there for exactly these purposes.
Get-ChildItem (aka gci, dir and ls)
(Get-Command -Name Get-ChildItem).Parameters.Keys
Get-Help -Name Get-ChildItem -Full
Get-Help -Name Get-ChildItem -Examples
Move-Item (aka mi, move, and mv)
(Get-Command -Name Move-Item).Parameters.Keys
Get-Help -Name Move-Item -Full
Get-Help -Name Move-Item -Examples
Remove-Item (aka del, erase, rd, ri, rm, rmdir)
(Get-Command -Name Remove-Item).Parameters.Keys
Get-Help -Name Remove-Item -Full
Get-Help -Name Remove-Item -Examples
See details here:
Files and Folders in Windows PowerShell
We’ll start out by telling you that everything you learned last month about manipulating files and folders with WMI will work in Windows PowerShell. PowerShell has a cmdlet called Get-WMIObject that allows you to access all the classes, methods and properties of WMI. Just like with VBScript, WMI is the only way to work with files and folders remotely in Windows PowerShell. We’re not going to get into working with WMI in Windows PowerShell in this article, but we’re going to show you the PowerShell way to work with files and folders.
https://technet.microsoft.com/en-us/library/ee176988.aspx
As for this...
"removing the two redundant "Archive" folders in between."
If there is nothing in these folders of value, then the above Remove-Item should be all you need. Otherwise you move all files from the to wherever, then remove the folders.
Or just use robocopy
https://technet.microsoft.com/en-us/library/cc733145(v=ws.11).aspx
https://social.technet.microsoft.com/wiki/contents/articles/1073.robocopy-and-a-few-examples.aspx
Robocopy (Robust File Copy) is a command-line file copy utility that comes with Windows Vista / Windows 2008 or newer. Until Vista, Robocopy was a part of Windows Resource Kit Tools as a free download (http://aka.ms/robocopydownload Jump ). Unlike normal copy commands, Robocopy is designed for reliable copy or mirroring while maintaining the permissions, attributes, owner information, timestamps and properties of the objects copied.

PowerShell New-Item Positional Parameter Oddities

Given the Microsoft documentation for PowerShell, I can see no reason why the following code should fail with the given error. Then again, PowerShell can fail when a script just gets too long. All the paths are double-quote strings.
##### ALGORITHM Take in keystore path, make a backup in an adjacent directory
$ksPath = $java_store_path.Substring(0, $java_store_path.LastIndexOf('\') + 1)
$backupPath = $ksPath + "backups"
New-Item $backupPath PowerShell -type directory -force
New-Item : A positional parameter cannot be found that accepts argument 'PowerShell'.
https://technet.microsoft.com/en-us/library/ee176914.aspx
New-Item c:\scripts\Windows PowerShell -type directory
If that's valid, mine should be too. I'm running on Server 2012 R2.
The example on that page is just plain wrong. It seems they meant to refer to the path C:\Scripts\WindowsPowerShell or they forgot to quote the directory with spaces in it.
So it should have been one of these:
New-Item c:\scripts\WindowsPowerShell -type directory
New-Item 'c:\scripts\Windows PowerShell' -type directory
New-Item "c:\scripts\Windows PowerShell" -type directory
Ask yourself, what would PowerShell alone have been referring to? What parameter would it have corresponded to?
Edit: as the commenters have pointed out, the example was supposed to show the nameSet parameters, where a separate -Path and -Name are specified, and purportedly PowerShell was supposed to be a value to the -Name parameter. That does look correct. The reason the example didn't work (and yours as well), is because the -Name parameter cannot be specified positionally, which you can see in the MSDN article I linked to below, and in the built-in help:
Type: String
Parameter Sets: nameSet
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
In that case, their example should have been something like these:
New-Item c:\scripts\Windows -Name PowerShell -type directory
New-Item -Path c:\scripts\Windows -Name PowerShell -type directory
So reiterating, named parameters would have worked here, and would have avoided confusion.
Generally, you shouldn't be using positional parameters in scripts, unless they're extremely clear (and even then, I'd recommend avoiding).
Using named parameters would have made this easier to figure out. And tab-completion helps with filling in the parameter names and in completing paths (usually with proper quoting too).
I think you should change yours to:
New-Item -Path $backupPath -Type Directory -Force
And looking over that technet article, it's really not so good. The MSDN article on New-Item is better, and this is the information you should see when running Get-Help New-Item as well.
Side question:
Then again, PowerShell can fail when a script just gets too long.
What?

search the files from multiple remote servers for specific file types

Could you help me for completing my small command , which i wrote for searching the files from remote servers around 150 servers across the regions
Invoke-Command -ComputerName (Get-Content F:\Serverlist.txt) -ScriptBlock {dir c:\ -Recurse -File | where {$_.Extension -eq ".pst"} |select Length,LastAccessTime,Name,#{n='Path';e={$_.fullname}},#{n='Owner';e={$_.getaccesscontrol().owner}}} |Export-Csv F:\files.csv -NoTypeInformation
Here I'm searching for .PST files from multiple servers in C drive , I want to include other drive F also in the above command.
Dir is an alias for Get-ChildItem, you can see this with Get-Alias dir.
If you would check the help with Get-Help Get-ChildItem -Full you'll see that -Path accepts multiple input:
-Path <String[]>
Specifies a path to one or more locations.
So I think the solution would be to replace:
dir c:\ with this Get-ChildItem C:, F:

Powershell command to copy only text files

I am trying to write a Powershell command to identify and copy only text (.txt) files from within a directory and sub-directories of that directory. Does anyone know if there is a command that can perform this task.
If you're not worried about maintaining the directory structure you could use
Get-ChildItem *.txt -recurse | Copy-Item -destination c:\qwerty
If you would like to maintain the directory structure you could use
Copy-Item -Recurse -Filter *.txt -path c:\temp -destination c:\asdf
NB.
The PowerShell get-help command is very useful and it does except wildcards.
ie
get-help *copy* gives you a list of commands that might be useful to you.
get-help Copy-Item -full gives you all the parameters plus examples of usage.

Find out whether a file is a symbolic link in PowerShell

I am having a PowerShell script which is walking a directory tree, and sometimes I have auxiliary files hardlinked there which should not be processed. Is there an easy way of finding out whether a file (that is, System.IO.FileInfo) is a hard link or not?
If not, would it be easier with symbolic links (symlinks)?
Try this:
function Test-ReparsePoint([string]$path) {
$file = Get-Item $path -Force -ea SilentlyContinue
return [bool]($file.Attributes -band [IO.FileAttributes]::ReparsePoint)
}
It is a pretty minimal implementation, but it should do the trick. Note that this doesn't distinguish between a hard link and a symbolic link. Underneath, they both just take advantage of NTFS reparse points, IIRC.
If you have Powershell 5+ the following one-liner recursively lists all file hardlinks, directory junctions and symbolic links and their targets starting from d:\Temp\:
dir 'd:\Temp' -recurse -force | ?{$_.LinkType} | select FullName,LinkType,Target
Output:
FullName LinkType Target
-------- -------- ------
D:\Temp\MyJunctionDir Junction {D:\exp\junction_target_dir}
D:\Temp\MySymLinkDir SymbolicLink {D:\exp\symlink_target_dir}
D:\Temp\MyHardLinkFile.txt HardLink {D:\temp\MyHardLinkFile2.txt, D:\exp\hlink_target.xml}
D:\Temp\MyHardLinkFile2.txt HardLink {D:\temp\MyHardLinkFile.txt, D:\exp\hlink_target.xml}
D:\Temp\MySymLinkFile.txt SymbolicLink {D:\exp\symlink_target.xml}
D:\Temp\MySymLinkDir\MySymLinkFile2.txt SymbolicLink {D:\temp\normal file.txt}
If you care about multiple targets for hardlinks use this variation which lists targets tab-separated:
dir 'd:\Temp' -recurse -force | ?{$_.LinkType} | select FullName,LinkType,#{ Name = "Targets"; Expression={$_.Target -join "`t"} }
You may need administrator privileges to run this script on say C:\.
Utilize Where-Object to search for the ReparsePoint file attribute.
Get-ChildItem | Where-Object { $_.Attributes -match "ReparsePoint" }
For those that want to check if a resource is a hardlink or symlink:
(Get-Item ".\some_resource").LinkType -eq "HardLink"
(Get-Item ".\some_resource").LinkType -eq "SymbolicLink"
My results on Vista, using Keith Hill's powershell script to test symlinks and hardlinks:
c:\markus\other>mklink symlink.doc \temp\2006rsltns.doc
symbolic link created for symlink.doc <<===>> \temp\2006rsltns.doc
c:\markus\other>fsutil hardlink create HARDLINK.doc \temp\2006rsltns.doc
Hardlink created for c:\markus\other\HARDLINK.doc <<===>> c:\temp\2006rsltns.doc
c:\markus\other>dir
Volume in drive C has no label.
Volume Serial Number is C8BC-2EBD
Directory of c:\markus\other
02/12/2010 05:21 PM <DIR> .
02/12/2010 05:21 PM <DIR> ..
01/10/2006 06:12 PM 25,088 HARDLINK.doc
02/12/2010 05:21 PM <SYMLINK> symlink.doc [\temp\2006rsltns.doc]
2 File(s) 25,088 bytes
2 Dir(s) 6,805,803,008 bytes free
c:\markus\other>powershell \script\IsSymLink.ps1 HARDLINK.doc
False
c:\\markus\other>powershell \script\IsSymLink.ps1 symlink.doc
True
It shows that symlinks are reparse points, and have the ReparsePoint FileAttribute bit set, while hardlinks do not.
here is a one-liner that checks one file $FilePath and returns if it is a symlink or not, works for files and directories
if((Get-ItemProperty $FilePath).LinkType){"symboliclink"}else{"normal path"}
Just want to add my own two cents, this is a oneliner function which works perfectly fine for me:
Function Test-Symlink($Path){
((Get-Item $Path).Attributes.ToString() -match "ReparsePoint")
}
The following PowerShell script will list all the files in a directory or directories with the -recurse switch. It will list the name of the file, whether it is a regular file or a hardlinked file, and the size, separated by colons.
It must be run from the PowerShell command line. It doesn't matter which directory you run it from as that is set in the script.
It uses the fslink utility shipped with Windows and runs that against each file using the hardlink and list switches and counts the lines of output. If two or greater it is a hardlinked file.
You can of course change the directory the search starts from by changing the c:\windows\system in the command. Also, the script simply writes the results to a file, c:\hardlinks.txt. You can change the name or simply delete everything from the > character on and it will output to the screen.
Get-ChildItem -path C:\Windows\system -file -recurse -force |
foreach-object {
if ((fsutil hardlink list $_.fullname).count -ge 2) {
$_.PSChildname + ":Hardlinked:" + $_.Length
} else {
$_.PSChildname + ":RegularFile:" + $_.Length
}
} > c:\hardlinks.txt