Good afternoon all,
I'm guessing this is super easy but really annoying for me; I have a text file with a list of files, in the same folders there are LOTS of other files but I only need specific ones.
$Filelocs = get-content "C:\Users\me\Desktop\tomove\Code\locations.txt"
Foreach ($Loc in $Filelocs){xcopy.exe $loc C:\Redacted\output /s }
I figured this would go through the list which is like
"C:\redacted\Policies\IT\Retracted Documents\Policy_Control0.docx"
and then move and create the folder structure in a new place and then copy the file, it doesn't.
Any help would be appreciated.
Thanks RGE
CodePudding user response:
xcopy
can't know the folder structure when you explicitly pass source file path instead of a source directory. In a path like C:\foo\bar\baz.txt
the base directory could be any of C:\
, C:\foo\
or C:\foo\bar\
.
When working with a path list, you have to build the destination directory structure yourself. Resolve paths from text file to relative paths, join with destination directory, create parent directory of file and finally use PowerShell's own Copy-Item
command to copy the file.
$Filelocs = Get-Content 'locations.txt'
# Base directory common to all paths specified in "locations.txt"
$CommonInputDir = 'C:\redacted\Policies'
# Where files shall be copied to
$Destination = 'C:\Redacted\output'
# Temporarily change current directory -> base directory for Resolve-Path -Relative
Push-Location $CommonInputDir
Foreach ($Loc in $Filelocs) {
# Resolve input path relative to $CommonInputDir (current directory)
$RelativePath = Resolve-Path $Loc -Relative
# Resolve full target file path and directory
$TargetPath = Join-Path $Destination $RelativePath
$TargetDir = Split-Path $TargetPath -Parent
# Create target dir if not already exists (-Force) because Copy-Item fails
# if directory does not exist.
$null = New-Item $TargetDir -ItemType Directory -Force
# Well, copy the file
Copy-Item -Path $loc -Destination $TargetPath
}
# Restore current directory that has been changed by Push-Location
Pop-Location
Possible improvements, left as an exercise:
- Automatically determine common base directory of files specified in "locations.txt". Not trivial but not too difficult.
- Make the code exception-safe. Wrap everything between
Push-Location
andPop-Location
in atry{}
block and movePop-Location
into thefinally{}
block so the current directory will be restored even when a script-terminating error occurs. See about_Try Catch_Finally.