I want to move some files from one place to another with saving of directory. Result of my script is broken encoding and it doesn't work. I use robocoby, because I have files with names more 256 simbols. I need to move files from different locations. And we are talking about several hundred files.
$source = Get-Content "C:\Users\bill\Downloads\111.TXT" -Encoding UTF8
$destination = "C:\Users\bill\OneDrive\Documents"
foreach($file in $source)
{
robocopy $file $destination /MOVE /E /copyall /log:C:\Users\bill\OneDrive\Documents\log.txt
}
Jane,
Try building your robocopy command like this:
*** UPDATED and TESTED ***
Clear-Host
$source = Get-Content "G:\Test\111.txt" -Encoding UTF8
$destination = "G:\BEKDocs\Test"
Foreach ($SrcPath in $source) {
$file = Split-Path -Path $SrcPath -Leaf
$path = Split-Path -Path $SrcPath -parent
$PLen = $Path.Length -3
$PAdd = $Path.Substring(3,$PLen)
$SavePath = Join-Path -Path $Destination -ChildPath $PAdd
$robocopyOptions = #('/Move', '/copyall')
$LogFile =
#('/log+:G:\BEKDocs\Transfer\log.txt')
$CmdLine = #($path, $SavePath, $file) +
$robocopyOptions + $LogFile
& 'robocopy.exe' $CmdLine
} #End Foreach
Note: Use single quotes as indicated!
Update notes:
Part of the problem was that you had the filenames attached to the paths in your file where RoboCopy wants SourcePath DestPath FileSpec as the first three arguments.
You're copying single files so there is no need for the Recurse /E parameter.
Since you want to preserve the directory structure you need to append the Source path, less the drive (d:) to your destination directory.
You're also calling RoboForm in a loop so you need the /Log+ parameter so each file is appended to the file rather than over writing it.
In my test I copied a file from the base directory, another from one level deep and a third from 2 levels deep. The code preserved the directory structure starting with the specified Destination as the Base or Root directory.
Took a bit of time to figure all this out but I wasn't going to let it go. Hope this works for you!
Related
I am pretty new to PowerShell and I need some help. I have a .bat file that I want to copy as many times as there are usernames in my array and then also rename at the same time. This is because the code in the .bat file remains the same, but for it to work on the client PC it has to have the username as a prefix in the filename.
This is the code that I have tried:
$usernames = Import-Csv C:\Users\Admin\Desktop\usernames.csv
$file = Get-ChildItem -Path 'C:\Users\Admin\Desktop\generatedbat\' -Recurse
foreach ($username in $usernames)
{
ForEach-Object {Copy-Item $file.FullName ('C:\Users\Admin\Desktop\generatedbat\' + $username + $File.BaseName + ".bat")}
}
This copies everything and it kind of works but I have one problem.
Instead of having this filename: JohnR-VPNNEW_up.bat
I get this: #{Username=JohnR}-VPNNEW_up.bat
Any help? Thanks!
So you have one .bat file C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat you want to copy to the same directory with new names taken from the usernames.csv --> Username column.
Then try
# get an array of just the UserNames column in the csv file
$usernames = (Import-Csv -Path 'C:\Users\Admin\Desktop\usernames.csv').Username
# get the file as object so you can use its properties
$originalFile = Get-Item -Path 'C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat'
foreach ($username in $usernames) {
$targetFile = Join-Path -Path $originalFile.DirectoryName -ChildPath ('{0}-{1}' -f $username, $originalFile.Name)
$originalFile | Copy-Item -Destination $targetFile -WhatIf
}
I have added switch -WhatIf so you can first test this out. If what is displayed in the console window looks OK, then remove that -WhatIf safety switch and run the code again so the file is actually copied
I kept the code the same but instead of using a .csv file I just used a .txt file and it worked perfectly.
I am trying to iterate the file path in the notepad (New_Test_File.txt) and by using the script I will open all these 5 files in a new file called "file_2"
My "New_Test_File.txt" is -
My Expectation Output is -
My script is -
$paths = Get-Content -Path C:\Users\JamesAlam\Desktop\New_Test_File.txt
foreach($path in $paths) {
Write-Host $path
ROBOCOPY /ZB /XO /R:3 /W:10 $path C:\Users\JamesAlam\Desktop\File_2
}
I am a newbie in PowerShell and I am not sure how to use the ROBOCOPY method to copy these file paths and open them in the new folder. Please help me with this. Thanks in advance
For each robocopy action you should have, in your case - "source", "destination", and "file" (optional - arguments).
So... You will need to specify the source folder as the directory only, and the file name.
Try to run this, it should work:
$paths = Get-Content -Path C:\Users\JamesAlam\Desktop\New_Test_File.txt
foreach($path in $paths) {
$directory = [System.IO.Path]::GetDirectoryName($path)
$fileName = Split-Path $path -leaf
robocopy $directory C:\Users\JamesAlam\Desktop\File_2 $fileName
}
I am running a powershell script, with the following
Copy-Item -Path c:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config -Destination c:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.orig
If the machine.orig already exists, how can i make it copy it to machine.orig1, and if that already exists, machine.orgin2?
If I may make a suggestion. Personally, I like the idea of a date/time stamp on the file rather than an incremental number. This way you know when the file was backed up, and you're far less likely to run into confusion over the file. Plus the script code is simpler.
Hope this helps.
$TimeStamp = get-date -f "MMddyyyyHHmmss"
$SourceFile = Dir c:\folder\file.txt
$DestinationFile = "{0}\{1}_{2}.{3}" -f $SourceFile.DirectoryName, $SourceFile.BaseName, $TimeStamp, $SourceFile.Extension
copy-Item $sourcefile $DestinationFile
#let us first define the destination path
$path = "R:\WorkindDirectory"
#name of the file
$file = "machine.orgin"
#let us list the number of the files which are similar to the $file that you are trying to create
$list = Get-ChildItem $path | select name | where name -match $file
#let us count the number of files which match the name $file
$a = ($list.name).count
#if such count of the files matching $file is less than 0 (which means such file dont exist)
if ($a -lt 1)
{
New-Item -Path $path -ItemType file -Name machine.orgin
}
#if such count of the files matching $file is greater than 0 (which means such/similar file exists)
if ($a -gt 0)
{
$file = $file+$a
New-Item -Path $path -ItemType file -Name $file
}
Note: This works assuming that the names of the files are in series. Let us say using this script you create
machine.orgin
machine.orgin1
machine.orgin2
machine.orgin3
and later delete machine.orgin2 and re run the same script then it won't work.
Here i have given an example where i have tried to create a new file and you can safely modify the same to copy such file using copy-item instead of new-item
I have a folder where files get dropped, I wish to pull the files from that folder and move to a new folder based on part of the file name. If the new folder is missing then create it.
I have attempted to put together the below, however it throws an error about the path already existing and doesn't move the file.
File names can be any thing with out pattern except the last 16 characters of the file, I am removing these and using the remaining as the folder name.
I am really new to scripting so if i have made a silly mistake explanations are appreciated.
Edit
I have played with different orders of operations, added a "-Force" to the new item command, tried with using "Else" and not "If (!(".
I am now at the point where it proudly displays the new directory and then stops.
Could i add the move-item part to a new for each loop so it is processed after the dir is created and tested? If so how do you arrange the { } parts?
Edit 2
I finally have it working, updated script below, the movie-item command was having issues when running into special characters in file names, in my case it was square brackets. The -literalpath switch fixed that for me.
Thanks every one for your input.
Updated script 3.0
#Set source folder
$source = "D:\test\source\"
#Set destination folder (up one level of true destination)
$dest = "D:\test\dest\"
#Define filter Arguments
$filter = "*.txt"
<#
$sourcefile - finds all files that match the filter in the source folder
$trimpath - leaves $file as is, but gets just the file name.
$string - gets file name from $trimpath and converts to a string
$trimmedstring - Takes string from $trimfile and removes the last 16 char off the end of the string
Test for path, if it exists then move on, If not then create directory
Move file to new destination
#>
pushd $source
$sourcefile = Get-ChildItem $source -Filter $filter
foreach ($file in $sourcefile){
$trimpath = $file | split-path -leaf
$string = $trimpath.Substring(0)
$trimmedstring = $string.Substring(0,$string.Length-16)
If(!(Test-Path -path "$dest\$trimmedstring")){New-Item "$dest\$trimmedstring" -Type directory -Force}
move-Item -literalpath "$file" "$dest\$trimmedstring"
}
You may have to tweak the paths being used but the below should work.
$sourcefiles = ((Get-ChildItem $source -Filter $filter).BaseName).TrimEnd(16)
foreach ($file in $sourcefiles)
{
if(!(Test-Path "$dest\$file")){
New-item -ItemType directory -path "$dest\$file"
}
Move-Item "$source\$file" "$dest\file"
}
I finally have it working, updated script below, the movie-item command was having issues when running into special characters in file names, in my case it was square brackets. The -literalpath switch fixed that for me. Thanks every one for your input.
#Set source folder
$source = "D:\test\source\"
#Set destination folder (up one level of true destination)
$dest = "D:\test\dest\"
#Define filter Arguments
$filter = "*.txt"
<#
$sourcefile - finds all files that match the filter in the source folder
$trimpath - leaves $file as is, but gets just the file name.
$string - gets file name from $trimpath and converts to a string
$trimmedstring - Takes string from $trimfile and removes the last 16 char off the end of the string
Test for path, if it exists then move on, If not then create directory
Move file to new destination
#>
pushd $source
$sourcefile = Get-ChildItem $source -Filter $filter
foreach ($file in $sourcefile){
$trimpath = $file | split-path -leaf
$string = $trimpath.Substring(0)
$trimmedstring = $string.Substring(0,$string.Length-16)
If(!(Test-Path -path "$dest\$trimmedstring")){New-Item "$dest\$trimmedstring" -Type directory -Force}
move-Item -literalpath "$file" "$dest\$trimmedstring"
}
I am trying to write a PowerShell script to do the following.
Rename files in source (FTP folders) directories with it's "current_name_datetime.csv" as per a source file "Source_list.csv" this file has the directories "source,destination" I want this script to look into.
Copy newly renamed files to backup directories as per destination in Source_list.csv this file has the directories "source,destination" I want this script to look into.
Move newly renamed files to final destination directory which is not in my current script.
Source_list.csv contents
cscenter,Costume_Supercenter
fkimports,FKImports
My Script:
$sdfiles = Get-Content c:\!tony\Source_list.csv
$sourceDir = "c:\test\"
$destinationDir = "c:\testing\"
Get-ChildItem $sourceDir -Recurse -Include $sdfiles "*.csv"|
ForEach-Object{
$newname= "{0}{1}_{2}.csv" -f $destinationDir, $_.BaseName, [datetime]::Now.ToString('MM-dd-yyyy-hh-mm-ss')
$_|Copy-Item -Include ,$sdfiles -Destination $newname -whatif }
Error:
What if: Performing operation "Copy Directory" on Target "Item: C:\test\cscenter Destination: C:\testing\cscenter_10-01-2015-12-22-24.csv".
I see in the error that it is trying to copy the directory not the single file in each directory and creating a new folder using the original folder name and renaming the folder and appending the date/time stamp.
Confused. The -Include parameter should only be accepting a single array of strings, throwing "*.csv" on to the end of it won't work AFAIK. Additionally It will be interpreting the whole line of the CSV, ie searching for the file "cscenter,Costume_Supercenter" so shouldn't be returning anything. At least that's what I see when I replicate this on my computer.
Lastly you've tried to filter the files, piped that to Copy-Item and tried to filter it again?
I'd take a more straightforward approach:
$sdfiles = Import-CSV c:\!tony\Source_list.csv -Header #("File", "Folder")
$sourcedir = "c:\test\"
$destinationdir = "c:\testing\"
$sdfiles | ForEach-Object {
$path = $sourcedir + $_.File + ".csv"
$folder = $destinationdir + $_.Folder + '\'
if (!(Test-Path $folder)) { New-Item -Type Directory -Path $folder }
if (Test-Path ($path))
{
$newname = "{0}{1}_{2}.csv" -f $folder, $_.File, (Get-Date).ToString('MM-dd-yyyy-hh-mm-ss')
Copy-Item -Path $path -Destination $newname -whatif
}
else { Write-Error "File $($_.File) not found" }
}
It's a bit chunkier but much easier to read and tweak to your liking. Note that Import-CSV does require PowerShell v3. Let me know if you've got v2 and need help tweaking it for a two-dimensional array.
I also recommend looking into Microsoft's MVA courses on PowerShell, they are excellent resources for starting out.