I wrote a powershell script that exports a bunch of files from a Dynamics NAV instance. It calls a perl script that I also wrote that then splits all of the files into individual objects and sticks them in subdirectories under a dir I create in perl. Then the powershell script attempts to copy the files to a different dir, and fails.
Powershell generates the dir name:
$datestamp = get-date -f MM-dd-yyyy_HH_mm_ss
$dumpdir = "\temp\nav_export\" + $env:username + "\" + $servicetier + "~" + $database + "~" + $datestamp;
Then powershell does a bunch of stuff that works fine, and calls the perl script ($servicetier and $database are defined earlier in the script):
& c:\navgit\split-objects.pl $servicetier $database $datestamp
perl proceeds to create the directory and split the files correctly:
use strict;
use warnings;
use File::Path qw(make_path remove_tree);
my $username = getlogin || getpwuid($<);
my $servicetier = $ARGV[0];
my $database = $ARGV[1];
my $datestamp = $ARGV[2];
undef #ARGV;
my $work_dir = "/temp/nav_export";
my $objects_dir = "$work_dir/$username/objects";
my $export_dir = "$work_dir/$username/$servicetier~$database~$datestamp";
print "Objects from $servicetier~$database being exported to $export_dir\n";
make_path("$export_dir/Page", "$export_dir/Codeunit", "$export_dir/MenuSuite", "$export_dir/Query", "$export_dir/Report", "$export_dir/Table", "$export_dir/XMLport");
chdir $objects_dir or die "Could not change to $objects_dir: $!";
<does all of the filehandling and parsing>
Control returns to the powershell script, which tries to finish with:
Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
But that throws the error:
Copy-Item : Cannot find path 'C:\temp\nav_export\danielj\cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50' because it does not exist.
At C:\navgit\nav-export.ps1:175 char:1
+ Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\temp\nav_exp...0-2015_19_26_50:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
The directory I'm trying to copy from does exist. But powershell doesn't see it! I added some code to list the contents of the parent dir:
Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse
Write-Host "Copy-Item -Path $dumpdir -Destination $cwd -Force -Recurse"
$test = "C:\temp\nav_export\$env:username"
Get-ChildItem $test -Force
Copy-Item -Path \temp\nav_export\danielj\cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50 -Destination C:\Users\danielj\erp\ -Force -Recurse
Directory: C:\temp\nav_export\danielj
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/20/2015 6:32 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_18_32_33
d---- 1/20/2015 7:08 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_08_49
d---- 1/19/2015 1:07 PM cen-dev-erp-st1~JustFoodERP-PROTO~20150119-130747
d---- 1/20/2015 7:26 PM logs
d---- 1/20/2015 7:26 PM objects
-a--- 1/20/2015 7:26 PM 309 objects.bat
-a--- 1/20/2015 1:41 PM 436 soap_envelope.txt
If I do a directory listing from outside the script, there it is:
PS C:\Users\danielj\erp> $test = "C:\temp\nav_export\$env:username"
Get-ChildItem $test -Force
Directory: C:\temp\nav_export\danielj
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/20/2015 6:32 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_18_32_33
d---- 1/20/2015 7:08 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_08_49
d---- 1/20/2015 7:26 PM cen-dev-erp-st1~JustFoodERP-PROTO~01-20-2015_19_26_50
d---- 1/19/2015 1:07 PM cen-dev-erp-st1~JustFoodERP-PROTO~20150119-130747
d---- 1/20/2015 7:26 PM logs
d---- 1/20/2015 7:26 PM objects
-a--- 1/20/2015 7:26 PM 309 objects.bat
-a--- 1/20/2015 1:41 PM 436 soap_envelope.txt
I've tried calling an external script from the main powershell script after perl is finished, and the results are the same.
Why would powershell not see the directory or files that were created by the perl script? And more importantly, how can I get it to do so?
Are you sure that everything proced in the exact order you assume it does ?
try to start your perl script like this :
& c:\navgit\split-objects.pl $servicetier $database $datestamp | Out-Null
It makes sure that your Perl part is terminated when the PowerShell execute the rest of your script.
I ended up just creating the directory in powershell in the first place. No reason it should have to have been created in the perl script.
It'd still be nice to know why it didn't work the way I'd have expected though.
Related
I have a folder with images that multiple people will be contributing, and I have multiple folders that other people will be creating with additional content, the folder names will be similar but not identical to the file names (see example below). I have tried writing a Powershell script (I'm still a bit green with it) that moves each image to its respective folder but I hit a wall, I'm getting the "Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Destination'. Specified method is not supported." I tried converting the destination to a string but had trouble looping through the list of folders. I'm adding the code here in hopes someone will spot the error I made in the code and will point me in the right direction. Thanks in advance for taking the time to help.
$sourceFolder = Get-ChildItem 'C:\Example_Files_Folder' -Recurse -Filter *.png
$targetFolder = Get-ChildItem -Path 'C:\Example_Target_Folder' -Recurse -Directory
foreach ($file in $sourceFolder) {
Where-Object { $targetFolder.Name -cin $sourceFolder.BaseName }
move-Item -Path $file.FullName -Destination $targetFolder.FullName -WhatIf
Write-Output "...copying $file"
}
<# ### Folder Structure
▼sourceFolder #Root Folder containing files
├───►looking inside this folder.png
├───►you should be able to find.png
├───►quite a long list of files.png
├───►matching many folders names.png
└───►that exist inside other folders.png
▼targetFolder #Root Folder
├───▼subfolder01
│ └───►looking inside #this is a folder
├───▼subfolder02
| └───▼subfolder002
| └───▼subfolder0002
| └───►you should be #also a folder
├───▼subfolder03
| └───►quite a long #not a file, just a folder
├───▼subfolder04
| └───►matching many folders #folder
├───▼subfolder05
| └───►sometimes with no matching file name #yep, a folder
├───▼subfolder06
| └─────►that exist within many folders #you get it
└───►subfolder07
### #>
Continuing from my comment ...
You can simplify this to say something like this:
# Target folder tree
$targetFolders = Get-ChildItem -Path 'D:\Temp\Target' -Recurse -Directory
# Results
<#
Directory: D:\Temp\Target
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 17-Feb-21 10:22 Book
d----- 17-Feb-21 10:10 TextData
Directory: D:\Temp\Target\Book
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 17-Feb-21 10:10 Date
#>
# Source folder files to move
Get-ChildItem 'D:\Temp' -Recurse -Filter '*.txt' |
ForEach {
ForEach ($targetFolder in $targetFolders)
{
If ($PSItem.BaseName -match $targetFolder.Name)
{Move-Item -Path $PSItem.FullName -Destination $targetFolder.FullName -WhatIf}
}
}
# Results
<#
What if: Performing the operation "Move File" on target "Item: D:\Temp\Book- Copy (2).txt Destination: D:\Temp\Target\Book\Book- Copy (2).txt".
....
What if: Performing the operation "Move File" on target "Item: D:\Temp\DateData.txt Destination: D:\Temp\Target\Book\Date\DateData.txt".
...
What if: Performing the operation "Move File" on target "Item: D:\Temp\TextData.txt Destination: D:\Temp\Target\TextData\TextData.txt".
#>
I need a script for windows to copy some files that contain a reference to a folder that has the name of the reference in their name.
Example: The file K:\examplefolder\sourcefolder\example3456file.pdf go to the folder K:\examplefolder\Destfolder\3456.
I created this:
$Src = 'K:\Escritorio\Scripts\Script_copiar_planos\Script OT\Origen'
$Dst = 'K:\Escritorio\Scripts\Script_copiar_planos\Script OT\Destino'
$file = 'K:\Escritorio\Scripts\Script_copiar_planos\Script OT\referencias.txt'
foreach ($referencia in Get-Content $file){
Get-ChildItem -Path $Src -Recurse -include *$referencia*.pdf -name -file | Copy-item -Destination $Dst\$referencia
}
In referencias.txt the references are listed like:
5678
91011
121314
For me apparently is okay, but when I go to execute the script it drops the following errors:
Copy-item : No se encuentra la ruta de acceso 'K:\Escritorio\Scripts\PDF-Con-81006600-en-el-nombre - copia (2).pdf' porque no existe.
En K:\Escritorio\Scripts\Script_copiar_planos\mover.ps1: 11 Carácter: 81
+ ... referencia*.pdf -name -file | Copy-item -Destination $Dst\$referencia
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (K:\Escritorio\S...- copia (2).pdf:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
When you pass argument -name to Get-ChildItem, it outputs only the file name portion of the path, e. g. "file1.pdf". This way Copy-Item has no information about the folder of the file and will use the working directory, whatever that happens to be before the call to Get-ChildItem.
Remove the argument -name to pass the full source path to Copy-Item:
Get-ChildItem -Path $Src -Recurse -include *$referencia*.pdf -file | Copy-item -Destination $Dst\$referencia
As a further optimization, you could replace -include by -filter, which is more efficient. From the docs:
Filters are more efficient than other parameters. The provider applies
filter when the cmdlet gets the objects rather than having PowerShell
filter the objects after they're retrieved.
Can someone help me understand why this scheduled script doesn't run as intended: The file is not reliably deleted at the start of the next day (runs correctly 3-4X out of 5 whether machine is powered on or out of sleep mode (S3). How to get it to always delete the previous day file?
$Path = "H:\foobar.txt"
if (Test-Path $Path) {Get-ChildItem $Path |
Where-Object { ($_.LastWriteTime).ToString() -lt ((get-date).AddDays(-1)).ToString() } |
Remove-Item -Force }
('{0:MMMM dd, yyyy h:mm:ss tt}' -f (Get-Date)) | Add-Content -Path $Path
EXIT
snippet from output showing carryover into next day:
April 27, 2020 9:31:18 PM
April 28, 2020 7:16:37 AM
April 28, 2020 5:31:45 PM
April 29, 2020 7:16:37 AM
April 29, 2020 11:17:02 PM
April 30, 2020 6:02:06 AM
April 30, 2020 6:17:02 PM
May 01, 2020 6:27:28 AM
May 01, 2020 7:17:02 AM
Seeing that the variable $Path contains the path to a single file, you could shorten the code like:
$Path = "H:\foobar.txt"
# try and get a FileInfo object from the file in the path
$file = Get-Item -Path $Path -ErrorAction SilentlyContinue
if ($file) {
# the file was found, check if it is older than yesterday (midnight)
if ($file.LastWriteTime -lt (Get-Date).AddDays(-1).Date) {
$file | Remove-Item -Force
}
}
# Add-Content will create the file if it does not yet exist
('{0:MMMM dd, yyyy h:mm:ss tt}' -f (Get-Date)) | Add-Content -Path $Path
Required of course is that the user running the scheduled task has write access to the H:\ path..
I am trying to get the target files from a folder with many .lnk shortcuts and put them in a new folder using Powershell. I have the following script and it runs but the output folder does not show anything:
$WScript = New-Object -ComObject WScript.Shell
Get-ChildItem -Path "<shortcut folder>*.lnk" | ForEach-Object {$WScript.CreateShortcut($_.FullName).TargetPath} | Out-File -FilePath "<Destination Folder>"
Branching off my comment to you. YOu can't Out-File a string, which is what is in the target path. It's not a real file. You can OUt-File that string to a text file if that is what you need, but that does not sound like what you are after.
Just step through each segment to make sure you are getting what you'd expect and use that target in a copy statement.
# Validate the lnk data
$WScript = New-Object -ComObject WScript.Shell
Get-ChildItem -Path "$env:USERPROFILE\Desktop\ClearIEData.lnk" | Format-Table -AutoSize
<#
# Results
Directory: C:\Users\postanote\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 28-Oct-18 00:52 1293 ClearIEData.lnk
#>
# Extract the lnk target path
$WScript = New-Object -ComObject WScript.Shell
Get-ChildItem -Path "$env:USERPROFILE\Desktop\ClearIEData.lnk" |
ForEach-Object {$WScript.CreateShortcut($_.FullName).TargetPath}
<#
# Results
D:\Tools\ClearIEData.cmd
#>
# Take needed action on the lnk target path info
$WScript = New-Object -ComObject WScript.Shell
Get-ChildItem -Path "$env:USERPROFILE\Desktop\ClearIEData.lnk" |
ForEach-Object {
Copy-Item -Path $($WScript.CreateShortcut($_.FullName).TargetPath) -Destination 'D:\temp' -WhatIf
}
<#
# Results
What if: Performing the operation "Copy File" on target "Item: D:\Tools\ClearIEData.cmd Destination: D:\temp\ClearIEData.cmd".
#>
If satisfied with the results, comment out or remove the -WhatIf and run the code again to take the action.
Get-ChildItem -Path 'D:\temp' -Filter 'ClearIEData.cmd'
<#
# Results
Directory: D:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 05-Mar-20 15:10 2571 ClearIEData.cmd
#>
$WScript = New-Object -ComObject WScript.Shell
Get-ChildItem -Path "$env:USERPROFILE\Desktop\ClearIEData.lnk" |
ForEach-Object {
$WScript.CreateShortcut($_.FullName).TargetPath | Out-File -FilePath 'D:\Temp\LinkFileData.txt' -Append -WhatIf
}
Get-Content -Path 'D:\Temp\LinkFileData.txt'
<#
# Results
D:\Tools\ClearIEData.cmd
#>
i am using following powershell script for getting folder with latest time stamp
$drive = get-psdrive |select root |Select-String -InputObject {$_.Root} -Pattern ':'
Write-Host $drive
foreach ($a in $drive)
{
Get-ChildItem -Path $a -Filter "*sysout" -Recurse -Force -ErrorAction SilentlyContinue|select -last 1
}
}
it gives following output
A:\ C:\ D:\ E:\ F:\ G:\ H:\ I:\ J:\ K:\ Z:\
Directory: E:\utility
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2/21/2018 2:06 AM sysout
Directory: F:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2/21/2018 3:15 AM sysout
i need latest timestamp folder but using -last 1 doesnt give desired results.
Last doesn't really have any meaning without order.
Get-ChildItem -Path $a -Filter "*sysout" -Recurse -Force -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -Last 1