I am not understanding what is happening.
I am attempting to copy and paste dll's from one directory and another.
gci -path $FromPath -Include ("*.dll", "*.pdp") | ? {$_.Name -match "appMaskA|appMaskB|appMaskC"} | foreach{Copy-item $_.Fullname -destination $ToPath -force}
Now that command works for one function that I have it in, but not for this one...
Now, this command is moving dll's to a different server. Not certain why it isn't working.
And if it isn't working it should throw an exception. I did wrap that command in a try catch by the way? Should I be catching a specific exception?
What does your $ToPath look like? If your code is wrapped in try/catch add -ErrorAction Stop parameter to your copy statement as the default value is to continue so the catch block will never be executed.
gci -path $FromPath -Include ("*.dll", "*.pdp") | ? {$_.Name -match "appMaskA|appMaskB|appMaskC"} | foreach{Copy-item $_.Fullname -destination $ToPath -force -ErrorAction Stop}
Does this need to be Powershell or can you use XCOPY via a BASH/CLI script. Using XCOPY you can access C Drive by doing
SERVER.DOMAIN.LOCAL/c$/path/to/dll
Maybe this works for you:
gci -path $FromPath -Include *.dll,*.pdp | where {$_.Name -match "appMaskA|appMaskB|appMaskC"} | Copy-item -path $_ -destination $ToPath -force
For complicated and/or large copying jobs I would use the program robocopy. Robocopy is part of Windows. Execute this command to verify its location:
Get-Command robocopy|select path
Related
Anyone knows how to delete all temp files using powershell.
Get-ChildItem $env:TEMP\TEMP | Remove-Item -confirm:$false -force -Recurse
I tired this code but it couldn't work.
Can you suggest me any better way to perform the same.
If you don't want to see any errors, you could use the -ErrorAction switch like this:
Remove-Item -Path $env:TEMP\* -Recurse -Force -ErrorAction SilentlyContinue
To empty TEMP folder and leave the folder in place, you should use this command:
Remove-Item $env:TEMP\* -Recurse
If you don't want to type so much, you can use also shorter version:
rm $env:TEMP\* -r
Just use this:
Remove-Item -Path $env:TEMP -Recurse -Force
Of course you will get access errors if any of the files you are deleting are actually being used by the system.
I'm running PS as LOCAdmin and run following command
PS C:\Windows\system32>$tempfolders = #(“C:\Windows\Temp\*”, “C:\Windows\Prefetch\*”, “C:\Documents and Settings\*\Local Settings\temp\*”, “C:\Users\*\Appdata\Local\Temp\*”)
PS C:\Windows\system32>Remove-Item $tempfolders -force -recurse
works for me :)
I am searching for a file in all the folders.
Copyforbuild.bat is available in many places, and I would like to search recursively.
$File = "V:\Myfolder\**\*.CopyForbuild.bat"
How can I do it in PowerShell?
Use the Get-ChildItem cmdlet with the -Recurse switch:
Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
I use this to find files and then have PowerShell display the entire path of the results:
dir -Path C:\FolderName -Filter FileName.fileExtension -Recurse | %{$_.FullName}
You can always use the wildcard * in the FolderName and/or FileName.fileExtension. For example:
dir -Path C:\Folder* -Filter File*.file* -Recurse | %{$_.FullName}
The above example will search any folder in the C:\ drive beginning with the word Folder. So if you have a folder named FolderFoo and FolderBar PowerShell will show results from both of those folders.
The same goes for the file name and file extension. If you want to search for a file with a certain extension, but don't know the name of the file, you can use:
dir -Path C:\FolderName -Filter *.fileExtension -Recurse | %{$_.FullName}
Or vice versa:
dir -Path C:\FolderName -Filter FileName.* -Recurse | %{$_.FullName}
When searching folders where you might get an error based on security (e.g. C:\Users), use the following command:
Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
Here is the method that I finally came up with after struggling:
Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*
To make the output cleaner (only path), use:
(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname
To get only the first result, use:
(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname | Select -First 1
Now for the important stuff:
To search only for files/directories do not use -File or -Directory (see below why). Instead use this for files:
Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}
and remove the -eq $false for directories. Do not leave a trailing wildcard like bin/*.
Why not use the built in switches? They are terrible and remove features randomly. For example, in order to use -Include with a file, you must end the path with a wildcard. However, this disables the -Recurse switch without telling you:
Get-ChildItem -File -Recurse -Path ./bin/* -Include *.lib
You'd think that would give you all *.libs in all subdirectories, but it only will search top level of bin.
In order to search for directories, you can use -Directory, but then you must remove the trailing wildcard. For whatever reason, this will not deactivate -Recurse. It is for these reasons that I recommend not using the builtin flags.
You can shorten this command considerably:
Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}
becomes
gci './path*/' -s -Include 'name*' | where {$_.PSIsContainer -eq $false}
Get-ChildItem is aliased to gci
-Path is default to position 0, so you can just make first argument path
-Recurse is aliased to -s
-Include does not have a shorthand
Use single quotes for spaces in names/paths, so that you can surround the whole command with double quotes and use it in Command Prompt. Doing it the other way around (surround with single quotes) causes errors
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat
Will also work
Try this:
Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse | Where-Object { $_.Attributes -ne "Directory"}
Filter using wildcards:
Get-ChildItem -Filter CopyForBuild* -Include *.bat,*.cmd -Exclude *.old.cmd,*.old.bat -Recurse
Filtering using a regular expression:
Get-ChildItem -Path "V:\Myfolder" -Recurse
| Where-Object { $_.Name -match '\ACopyForBuild\.[(bat)|(cmd)]\Z' }
To add to #user3303020 answer and output the search results into a file, you can run
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat > path_to_results_filename.txt
It may be easier to search for the correct file that way.
On a Windows system:
Search for all .py files in the 'c:\temp' dir and subdirs, type: dir -r *.py or dir *.py -r
On a *Nix (Linux / MacOs system:
at the terminal type: find /temp -name *.py
This works fine for me.
Generally, robocopy is the fastest and simplest way for searching multiple files in parallel threads. It needs a quite good Powersell code with parallelism to beat that. Here is a link to an article I have written in the past with all the different options you have: Fastest way to find a full path of a given file via Powershell? Check the accepted answer for the best code.
Looking around the site and can't seem to find some answers for myself.
I'm looking to write a script, that will enable me to move files from one destination to another, based on the contents within the file.
To get into Specifics
Source Destination - V:\SW\FromSite
Copy to Destination - V:\SW\ToSW
FileType - .txt
String - test
Ideally I'd also like to ONLY have the script search files that begin with 7. These are unique identifiers to a region.
Pulling my hair out a bit trying.
I was using the below, which runs without error, but does nothing.
$DestDir = "V:\SW\FromSite"
$SrcDir = "V:\SW\ToSW"
$SearchString = "test"
gci $SrcDir -filter 7*.txt | select-string $SearchString | select path |
move-item -dest $DestDir -whatif
Here's what I would do, though I'm sure there's a more streamlined way to do it.
$files = gci $SrcDir -filter 7*.txt
$files | %{
if ((select-string -path $_.FullName -pattern $SearchString) -ne $null) {
move-item -path $_.FullName -dest $DestDir
}
}
So did some more messing around and the below is working perfectly for what I need
get-childitem "<SourceFolder>" -filter 7*.txt -
recurse | select-string -list -pattern "test" | move -dest "<DestinationFolder>"
Thanks all for the help
Not sure if I missed something (didn't tried it on my machine) - but as long as you pass the -whatif option, move-item "shows what would happen if the cmdlet runs. The cmdlet is not run."; see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/move-item.
So probably it would have been sufficient to just remove the -whatif from the initial statement.
I am currently new at PowerShell and I have created a script based on gathered information on the net that will perform a Delete Operation for found files within a folder that have their LastWriteTime less than 1 day.
Currently the script is as follows:
$timeLimit = (Get-Date).AddDays(-1)
$oldBackups = Get-ChildItem -Path $dest -Recurse -Force -Filter "backup_cap_*" |
Where-Object {$_.PSIsContainer -and $_.LastWriteTime -lt $timeLimit}
foreach($backup in $oldBackups)
{
Remove-Item $dest\$backup -Recurse -Force -WhatIf
}
As far as I know the -WhatIf command will output to the console what the command "should" do in real-life scenarios. The problem is that -WhatIf does not output anything and even if I remove it the files are not getting deleted as expected.
The server is Windows 2012 R2 and the command is being runned within PowerShell ISE V3.
When the command will work it will be "translated" into a task that will run each night after another task has finished backing up some stuff.
I did it in the pipe
Get-ChildItem C:\temp | ? { $_.PSIsContainer -and $_.LastWriteTime -lt $timeLimit } | Remove-Item -WhatIf
This worked for me. So you don't have to ttake care of the right path to the file.
other solution
$timeLimit = (Get-Date).AddDays(-1)
Get-ChildItem C:\temp2 -Directory | where LastWriteTime -lt $timeLimit | Remove-Item -Force -Recurse
The original issue was $dest\$backup would assume that each file was in the root folder. But by using the fullname property on $backup, you don't need to statically define the directory.
One other note is that Remove-Item takes arrays of strings, so you also could get rid of the foreach
Here's the fix to your script, without using the pipeline. Note that since I used the where method this requires at least version 4
$timeLimit = (Get-Date).AddDays(-1)
$Backups = Get-ChildItem -Path $dest -Directory -Recurse -Force -Filter "backup_cap_*"
$oldBackups = $backups.where{$_.LastWriteTime -lt $timeLimit}
Remove-Item $oldBackups.fullname -Recurse -Force -WhatIf
I am not certain I understand where I am going wrong.
I basically have the same command copying and pasting files for different instances. I guess I could have built it more object oriented, so I can solve the problem once and apply it for different instances, but this is a freaking script, and I just want to copy over dll's and pdb's...
gci -path $FromPath\* -Include *.dll, *pdb | ? {$_.Name -match "example1|example2|example3|example4|example5"} | foreach{
write-host("File being moved: "+ $_.Fullname) Copy-item $_.Fullname -destination $ToPath -force
}
The above works and sends dll's and pdb's to the correct directory.
gci -path $FromPath\* -Include *.dll, *pdb | ? {$_.Name -match "example1|example2|example3|example4"}| foreach{
write-host("File being moved: "+ $_.Fullname) Copy-item $_.Fullname -destination $ToPath -force
}
That does not. For whatever reason my pdb's don't go over with my dll's. I can't understand why it only grabs the dll and not the pdb. It lists both of them if I write out, why doesn't it move over both of them?