Trying to copy an updated shortcut to a wildcard path. The code works when I run it in a test scenario on the local machine:
$Source1 = "C:\Temp\Updated Shortcut\MyShortcut.lnk"
$destination1 = "C:\Temp\Users\*\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\MyShortcut.lnk"
Get-ChildItem -Path $destination1 | ForEach-Object { Copy-Item -Path $Source1 -Destination $_.DirectoryName }
But running it against the production target path does not work:
$Source1 = "C:\Temp\Updated Shortcut\MyShortcut.lnk"
$destination1 = "U:\Users\*\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\MyShortcut.lnk"
Get-ChildItem -Path $destination1 | ForEach-Object { Copy-Item -Path $Source1 -Destination $_.DirectoryName }
It will also work if I remove the wildcard and use an actual path:
$Source1 = "C:\Temp\Updated Shortcut\MyShortcut.lnk"
$destination1 = "U:\Users\JohnSmith\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\MyShortcut.lnk"
Get-ChildItem -Path $destination1 | ForEach-Object { Copy-Item -Path $Source1 -Destination $_.DirectoryName }
The U:\Users folder does contain 1181 folders in there (one for each of the 1181 users), so not sure if that may be an issue too??
Just because code can be written on one line or using a pipeline, does not mean that code is easy to debug or maintain.
Break your code down, debug it, add some logging, etc.
$Source1 = "C:\Temp\Updated Shortcut\MyShortcut.lnk"
$destination1 = "U:\Users\*\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\MyShortcut.lnk"
$items = Get-ChildItem -Path $destination1
Write-Verbose "Number of items: $($items.Count)" -Verbose
foreach ($item in $items)
{
Write-Verbose "Item: $item" -Verbose
# use -Force here? Does $_ have a DirectoryName property?
#
#Copy-Item -Path $Source1 -Destination $_.DirectoryName
Copy-Item -Path $Source1 -Destination $item -Force -WhatIf
}
My guess is that once you start looking into the diagnostics, you will isolate the issues quickly.
Related
I need to make basic / or more advanced backup script that would copy items from folder A to folder B and then log what it did.
This copies the files just fine:
$source = 'path\gamybinis\*'
$dest = 'path\backup'
Get-ChildItem -Path $source -Recurse | Where-Object { $_.LastWriteTime -gt [datetime]::Now.AddMinutes(-5)
}| Copy-Item -Destination $dest -Recurse -Force
Write-Host "Backup started"
Pause
But after this I can't write the log with | Out-File, So I've tried this:
$source = 'path\gamybinis\*'
$dest = 'path\backup'
$logFile = 'path\log.txt'
$items = Get-ChildItem -Path $source -Recurse | Where-Object { $_.LastWriteTime -gt [datetime]::Now.AddMinutes(-5)
}
foreach($item in $items){
Out-File -FilePath $logFile -Append
Copy-Item -Path "$source\$item" -Destination $dest -Recurse -Force
}
Write-Host "Backup started"
Pause
This one does absolutely nothing, what exactly am I doing wrong?
(Advanced script part would be: backing up recently modified files then files should be archived to .rar/.zip, log file have to have structure that is easily readable and log file should have information which user was working on the device during the backup) - For those who are wondering.
If you can't use robocopy, in pure PowerShell code you could do this
$source = 'path\gamybinis' # no need for '\*' because you're specifying -Recurse
$dest = 'path\backup'
$logFile = 'path\log.txt'
# test if the destination path exists. If not, create it first
if (!(Test-Path -Path $dest -PathType Container)) {
$null = New-Item -Path $dest -ItemType Directory
}
Write-Host "Backup started"
Get-ChildItem -Path $source -Recurse |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-5) } |
ForEach-Object {
$_ | Copy-Item -Destination $dest -Recurse -Force
Add-Content -Path $logFile -Value "$((Get-Date).ToString("yyyy-MM-dd HH:mm:ss")) - Copied file '$($_.FullName)'"
}
Write-Host "Backup done"
From your comments, I understand you have problems when using the -Container switch.
Below code does not use that and creates the folder structure of the copied files in the backup folder, strictly using Powershell code:
$source = 'path\gamybinis' # no need for '\*' because you're specifying -Recurse
$dest = 'path\backup'
$logFile = 'path\log.txt'
Write-Host "Backup started"
Get-ChildItem -Path $source -File -Recurse |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-5) } |
ForEach-Object {
$target = Join-Path -Path $dest -ChildPath $_.DirectoryName.Substring($source.Length)
if (!(Test-Path $target -PathType Container)) {
# create the folder if it does not already exist
$null = New-Item -Path $target -ItemType Directory
}
$_ | Copy-Item -Destination $target -Force
Add-Content -Path $logFile -Value "$((Get-Date).ToString("yyyy-MM-dd HH:mm:ss")) - Copied file '$($_.FullName)'"
}
Write-Host "Backup done"
I got a script:
$CopySource = "C:\Source\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
$CopyDestination = "C:\Dest\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
$files = Get-ChildItem -File "*.qvd" $CopySource -Force
foreach ($file in $files) {
Copy-Item -path $CopySource\$_$file -Destination $CopyDestination -Force
}
$CopySource = "C:\Source\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
$CopyDestination = "C:\Dest\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
$items = Get-ChildItem -File "*.qvd" $CopyDestination
foreach($I in $Items) {
$newfilename= rename-item -path $I.Name -newname ("Agresso_" + $I.Name)
The problem I have is that I need to copy files from source to destination and once they are over they need to have agresso_ added. Then they day after a batch of files will be copied again and also they need to be renamed to agresso_ and overwrite the old ones, preferably with move-item. I got a problem already, as I am not used with prefixes,
I tried enless of versions with where-object and simular, could not figure out a way to use test-path either.
I did exactly this but with renaming the files, like this for maximo:
$files = Get-ChildItem -File "*.qvd" $CopySource -Force
foreach ($file in $files) {
Copy-Item -path $CopySource\$_$file -Destination $CopyDestination -Force -Verbose 4>&1 |
Out-File -Append $logpath
}
"Klar med Kopiering av .qvd filer $global:currenttime" | Out-File $logpath -Append
"Påbörjar omdöpning av .qvd filer $global:currenttime" | Out-File $logpath -Append
$items = Get-ChildItem -File "*.qvd" $CopyDestination
foreach($I in $Items) {
$newfilename=$I.Name.Replace("QVDLager1","Maximo")
Move-Item -Path $I.FullName -Destination $CopyDestination\$newfilename -Force -Verbose 4>&1 |
Out-File -Append $logpath
If anyone can help me in the right direction it would be highly appriciated.
You can copy (or move) and rename the destination at the same time:
$CopySource = "C:\Source\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
$CopyDestination = "C:\Dest\Qlikview Storage\PrivateData\Gemensamma\Qvd_Raw\Agresso"
Get-ChildItem -Path $CopySource -File "*.qvd" -Force | ForEach-Object {
# create the full path for the target file with "Agresso_" prefixed
$target = Join-Path -Path $CopyDestination -ChildPath ('Agresso_{0}' -f $_.Name)
$_ | Copy-Item -Destination $target -WhatIf
}
If satisfied with the results of the code shown in the console, you can remove the -WhatIf switch to really start copying (or moving) the files.
I'm targeting simple task.
I would like to create folder of constant name "jpg" in all subfolders of supplied root folder "D:Temp\IMG" and move all files in every subfolder with extension ".jpg" to that newly created "jpg" folder.
I thought I'll be able to solve this by myself without deep knowledge of powershell, but it seems I have to ask.
So far, I created this code
$Directory = dir D:\Temp\IMG\ | ?{$_.PSISContainer};
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.FullName)" -File -Recurse -Filter '*.jpg' |
ForEach-Object {
$Dest = "$($d.DirectoryName)\jpg"
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force}
Move-Item -Path $_.FullName -Destination $Dest
}
}
What I'm getting out of this is infinite loop of folder "jpg" creation in every subfolder.
Where is my code and logic failing here, please?
The following script would do the job.
$RootFolder = "F:\RootFolder"
$SubFolders = Get-ChildItem -Path $RootFolder -Directory
Foreach($SubFolder in $SubFolders)
{
$jpgPath = "$($SubFolder.FullName)\jpg"
New-Item -Path $jpgPath -ItemType Directory -Force
$jpgFiles = Get-ChildItem -Path $SubFolder.FullName -Filter "*.jpg"
Foreach($jpgFile in $jpgFiles)
{
Move-Item -Path $jpgFile.FullName -Destination "$jpgPath\"
}
}
This will accomplish what you are attempting, I'm pretty sure. Your original script doesn't actually recurse, despite specifying that you want it to (Get-ChildItem has some finicky syntax around that), so I fixed that. Also fixed my suggestion (I forgot that the Extension property includes the preceding dot, so 'FileName.jpg' has '.jpg' as the extension). I added in some checking, and have it throw warnings if the file already exists at the destination.
$Directory = dir D:\Temp\IMG\ -Directory
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.fullname)\*" -File -Recurse -filter '*.jpg' |
Where{$_.Directory.Name -ne $_.Extension.TrimStart('.')}|
ForEach-Object {
$Dest = join-path $d.FullName $_.Extension.TrimStart('.')
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force|Out-Null}
If(Test-Path ($FullDest = Join-Path $Dest $_.Name)){
Write-Warning "Filename conflict moving:`n $($_.FullName)`nTo:`n $FullDest"
}Else{
Move-Item -Path $_.FullName -Destination $Dest -Verbose
}
}
}
I need to copy all of my c:\inetpub directory to a new location but exclude the following folders and their subfolders:
c:\inetpub\custerr
c:\inetpub\history
c:\inetpub\logs
c:\inetpub\temp
c:\inetpub\wwwroot
So far I am doing this:
# Directory name is created with a format string
$dirName = "\\servername\folder1 _ {0}\inetpub" -f (get-date).ToString("yyyy-MM-dd-hh-mm-ss")
$dirName # Check the output
# Create dir if needed
if(-not (test-path $dirName)) {
md $dirName | out-null
} else {
write-host "$dirName already exists!"
}
#Copy Backup File to Dir
Copy-Item "\\servername\c$\inetpub\*" $dirName -recurse
This is a simple example of something you could do. Build an array of the parent folders that you want to exclude. Since you are accessing them via UNC paths we cannot really use the c:\ path (We can get around this but what I am about to show should be good enough.).
Then use Get-ChildItem to get all the folders in the inetpub directory. Filter out the exclusions using -notin and pass the rest to Copy-Item
$excludes = "custerr","history","logs","temp","wwwroot"
Get-ChildItem "c:\temp\test" -Directory |
Where-Object{$_.Name -notin $excludes} |
Copy-Item -Destination $dirName -Recurse -Force
You need at least PowerShell 3.0 for this to work.
Copy-Item -Path (Get-Item -Path "$path\*" -Exclude ('Folder1', 'File.cmd', 'File.exe', 'Folder2')).FullName -Destination $destination -Recurse -Force
Replace:
$path by your source folder
('Folder1', 'File.cmd', 'File.exe', 'Folder2') by your specific files/folder to exclude
$destination by your destination folder
Oh, the answer was SO simple, but it seems we are all PowerShell noobs.
New-Item -ItemType Directory -Force -Path $outDir # directory must exist
Copy-Item $inDir\* $outDir -Exclude #("node_modules",".yarn") -Recurse
It's the \* that makes it work.
PowerShell is awesome, but...
I wrote this for daily use and packaged it in the script module, it maintains all the directory structure and supports wildcards:
function Copy-Folder {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[String]$FromPath,
[Parameter(Mandatory)]
[String]$ToPath,
[string[]] $Exclude
)
if (Test-Path $FromPath -PathType Container) {
New-Item $ToPath -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
Get-ChildItem $FromPath -Force | ForEach-Object {
# avoid the nested pipeline variable
$item = $_
$target_path = Join-Path $ToPath $item.Name
if (($Exclude | ForEach-Object { $item.Name -like $_ }) -notcontains $true) {
if (Test-Path $target_path) { Remove-Item $target_path -Recurse -Force }
Copy-Item $item.FullName $target_path
Copy-Folder -FromPath $item.FullName $target_path $Exclude
}
}
}
}
Just call the Copy-Folder -FromPath inetpub -ToPath new-inetpub -Exclude custerr,history,logs,temp,wwwroot
The -FromPath and -ToPath can be omitted,
Copy-Folder inetpub new-inetpub -Exclude custerr,history,logs,temp,wwwroot
You can do something along the lines of:
?{$_.fullname -notmatch '\\old\\'}
after you get a hold of all your folders to filter them down.
This example would exclude anything containing "old" in the name. You can do this for directory you wish to exclude.
A full example:
C:\Example*" -include "*.txt -Recurse |
?{$_.fullname -notmatch '\\old\\'}|
% {Copy-Item $_.fullname "C:\Destination\"}
For multiple excludes you can use -And :
C:\Example*" -include "*.txt -Recurse |
?{$_.fullname -notmatch '\\old\\' -And $_.fullname -notmatch '\\old2\\'}|
% {Copy-Item $_.fullname "C:\Destination\"}
I want to copy a folder to a range of computers on my LAN. Here is what I have so far:
$Computers = "Get-Content C:\Scripts\computers.txt"
$Source = "C:\Install\9_10_00_08HotFix_201504140001"
$Destination = "\\192.168.6.$\c$\Install"
ForEach-Object {
Copy-Item -Path $Source -Recurse -Destination $Destination -Verbose -Force -ErrorAction SilentlyContinue
}
You didn't say what your actual problem is, but it's probably that you misplaced the first double quote in the Get-Content statement, that you can't define a variable destination like you do, and that you don't do anything with what you (try to) read from computers.txt.
Change this:
$Computers = "Get-Content C:\Scripts\computers.txt"
$Source = "C:\Install\9_10_00_08HotFix_201504140001"
$Destination = "\\192.168.6.$\c$\Install"
ForEach-Object {
Copy-Item -Path $Source -Recurse -Destination $Destination -Verbose -Force -ErrorAction SilentlyContinue
}
into this:
$Computers = Get-Content "C:\Scripts\computers.txt"
$Source = "C:\Install\9_10_00_08HotFix_201504140001"
$Computers | ForEach-Object {
Copy-Item -Path $Source -Recurse -Destination "\\192.168.6.$_\c$\Install" -Verbose -Force -ErrorAction SilentlyContinue
}
and your code should work.