Moving files not woking in powershell - powershell

I have a code:
cls
$folderPath = 'Y:\lit\Retail\abc\abc\FTP-FromClient\AMS\2022-03-23'
$files = Get-ChildItem $folderPath
$destination='Y:\lit\Retail\abc\abc\FTP-FromClient\AMS\2022-03-23\bz2'
$leftfiles=('20220322054419',
'20220322083959',
'20220322084715',
'20220322085207',
'20220322085250',
'20220322085858',
'20220322090236',
'20220322090410',
'20220322090450'
'20220322170306')
foreach($j in $leftfiles)
{
foreach($f in $files)
{
if ($f -contains $j)
{
Move-Item $f.FullName $destination
}
}
}
In this $folderPath I have some files:
$folderPath = 'Y:\lit\Retail\abc\abc\FTP-FromClient\AMS\2022-03-23'
File naming has some naming convention as which matches with the numbers inside the aray:
Colly_20220322054419.dat.bz2
Colly_1_20220322084715.dat.bz2
Colly_3_20220322085207.dat
I only need to move all the files to the destination ,if filename contains the number inside array elements. So I tried using -contains to move the file but it's not working:
foreach($j in $leftfiles)
{
foreach($f in $files)
{
if ($f -contains $j)
{
Move-Item $f.FullName $destination
}
}
}

Your code could be simplified if you use a Where-Object clause that filters the files to move using the regex -match operator
$folderPath = 'Y:\lit\Retail\abc\abc\FTP-FromClient\AMS\2022-03-23'
$destination = 'Y:\lit\Retail\abc\abc\FTP-FromClient\AMS\2022-03-23\bz2'
$leftfiles = '20220322054419', '20220322083959','20220322084715','20220322085207','20220322085250',
'20220322085858','20220322090236','20220322090410','20220322090450','20220322170306'
# first make sure the destination folder exists
$null = New-Item -Path $destination -ItemType Directory -Force
# join the items from $leftfiles with a pipe symbol (=the regex 'OR')
$regex = $leftfiles -join '|'
Get-ChildItem -Path $folderPath -File |
Where-Object { $_.BaseName -match $regex } |
Move-Item -Destination $destination
If you want to test this out first, append switch -WhatIf to the Move-Item line. THat way, nothing actually gets moved. Only in the console, it is displayed what would be moved

Related

PowerShell - Find duplicate file inside ZIPs and CABs

I am trying to write a script that will find duplicate file inside a compressed files.
The compressed files can be ZIP or CAB (Need help to extract CAB file also because currently its not working).
What I have so far is to extract the zips to a temp folder (don't know how to extract cab) and if there is a vip inside I need to extract him also to the same folder. currently all the files are extracted to the same temp folder what I need is to extract each zip/cab into a folder with the original name even if he has a vip inside. (the zip/cab are not flat) in the next step I need to find duplication files and display all the duplication and where they found.
The script below is not working...
$tempFolder = Join-Path ([IO.Path]::GetTempPath()) (New-GUID).ToString('n')
$compressedfiles = Get-ChildItem -path C:\Intel\* -Include "*.zip","*.CAB"
foreach ($file in $compressedfiles) {
if ($file -like "*.zip") {
$zip = [System.IO.Compression.ZipFile]::ExtractToDirectory($file, $tempFolder)
$test = Get-ChildItem -path $tempFolder\* -Include "*.vip"
if ($test) {
$zip = [System.IO.Compression.ZipFile]::ExtractToDirectory($test, $tempFolder)
}
}
}
$Files=gci -File -Recurse -path $tempFolder | Select-Object -property FullName
$MatchedSourceFiles=#()
ForEach ($SourceFile in $Files)
{
$MatchingFiles=#()
$MatchingFiles=$Files |Where-Object {$_.name -eq $SourceFile.name}
if ($MatchingFiles.Count -gt 0)
{
$NewObject=[pscustomobject][ordered]#{
File=$SourceFile.FullName
#MatchingFiles=$MatchingFiles
}
$MatchedSourceFiles+=$NewObject
}
}
$MatchedSourceFiles
Remove-Item $tempFolder -Force -Recurse
Building on what you have already tried, you could do this like:
Add-Type -AssemblyName System.IO.Compression.FileSystem
$tempFolder = Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath (New-GUID).Guid
$compressedfiles = Get-ChildItem -Path 'C:\Intel' -Include '*.zip','*.CAB' -File -Recurse
$MatchedSourceFiles = foreach ($file in $compressedfiles) {
switch ($file.Extension) {
'.zip' {
# the destination folder should NOT already exist here
$null = [System.IO.Compression.ZipFile]::ExtractToDirectory($file.FullName, $tempFolder)
Get-ChildItem -Path $tempFolder -Filter '*.vip' -File -Recurse | ForEach-Object {
$null = [System.IO.Compression.ZipFile]::ExtractToDirectory($_.FullName, $tempFolder)
}
}
'.cab' {
# the destination folder MUST exist for expanding .cab files
$null = New-Item -Path $tempFolder -ItemType Directory -Force
expand.exe $file.FullName -F:* $tempFolder > $null
}
}
# now see if there are files with duplicate names
Get-ChildItem -Path $tempFolder -File -Recurse | Group-Object Name |
Where-Object { $_.Count -gt 1 } | ForEach-Object {
foreach ($item in $_.Group) {
# output objects to be collected in $MatchedSourceFiles
[PsCustomObject]#{
SourceArchive = $file.FullName
DuplicateFile = '.{0}' -f $item.FullName.Substring($tempFolder.Length) # relative path
}
}
}
# delete the temporary folder
$tempFolder | Remove-Item -Force -Recurse
}
# display on screen
$MatchedSourceFiles
# save as CSV file
$MatchedSourceFiles | Export-Csv -Path 'X:\DuplicateFiles.csv' -UseCulture -NoTypeInformation
The output would be something like this:
SourceArchive DuplicateFile
------------- -------------
D:\Test\test.cab .\test\CA2P30.BA0
D:\Test\test.cab .\test\dupes\CA2P30.BA0
D:\Test\test.zip .\test\CA2P3K.DAT
D:\Test\test.zip .\test\dupes\CA2P3K.DAT
D:\Test\test.zip .\test\CA2P60.BA0
D:\Test\test.zip .\test\dupes\CA2P60.BA0

Moving Files based on filename

Im looking to move files based on the last half of the filename. Files look like this
43145123_Stuff.zip
14353135_Stuff.zip
2t53542y_Stuff.zip
422yg3hh_things.zip
I am only looking to move files that end in Stuff.zip
I have this in PowerShell so far but it only will move files according to the first half of a file name.
#set Source and Destination folder location
$srcpath = "C:\Powershelltest\Source"
$dstpath = "C:\Powershelltest\Destination"
#Set the files name which need to move to destination folder
$filterLists = #("stuff.txt","things")
#Get all the child file list with source folder
$fileList = Get-ChildItem -Path $srcpath -Force -Recurse
#loop the source folder files to find the match
foreach ($file in $fileList)
{
#checking the match with filterlist
foreach($filelist in $filterLists)
{
#$key = $file.BaseName.Substring(0,8)
#Spliting value before "-" for matching with filterlists value
$splitFileName = $file.BaseName.Substring(0, $file.BaseName.IndexOf('-'))
if ($splitFileName -in $filelist)
{
$fileName = $file.Name
Move-Item -Path $($file.FullName) -Destination $dstpath
}
}
}
There seems to be some differences between the state goal and what the code actually does. This will move the files to the destination directory. When you are confident that the files will be moved correctly, remove the -WhatIf from the Move-Item command.
$srcpath = "C:\Powershelltest\Source"
$dstpath = "C:\Powershelltest\Destination"
Get-ChildItem -File -Recurse -Path $srcpath |
ForEach-Object {
if ($_.Name -match '.*Stuff.zip$') {
Move-Item -Path $_.FullName -Destination $dstpath -WhatIf
}
}
Actually this can be written in PowerShell very efficiently (I hope I got the details right, let me know):
Get-ChildItem $srcpath -File -Force -Recurse |
where { ($_.Name -split "_" | select -last 1) -in $filterLists } |
Move-Item $dstpath
Alternatively, if you only want to look for this one particular filter, you can specify that directly, using wildcards:
Get-ChildItem $srcpath -Filter "*_Stuff.zip"

Trying to use powershell to put files in folders based on their extension and the name of the folder

I have a directory with three files: .xlsx, .docx, and .txt, I also have folders in that same directory called xlsx, docx and txt. Basically trying to put each file into its corresponding folder, as a way to practice my PowerShell skills. I'm very new to PowerShell and have tried the following. I can tell its wrong, but I'm not quite sure why.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
foreach ($folder in $folders) {
if ("*$file.extension*" -like "*$folder.Name*") {
move-item $file -Destination "C:\Users\userA\Desktop\$folder.name"
}
}
}
Try the code below. With the Where-Object function, you find the corresponding file. I remove the dot because it is included in the extension otherwise.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
$folder = $folders | Where-Object { $_.Name -Like $file.Extension.Replace(".","") }
Move-Item -Path $file -Destination $folder
}
In your example, be careful how your strings are actually been interpreted. If you have "*$item.Name*" the string actually "* variable.Name*". In this case you need to use "*$($var.Name)*" in order to get the correct string.
Here are some adjustments to your approach that make it work. Breaking the -Destination parameter out to a separate variable $newpath lets you set a debug statement there so you can easily examine what it's creating.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
foreach ($folder in $folders) {
if ($file.extension.trim(".") -like $folder.Name) {
$newpath = ("{0}\{1}" -f $folder.FullName, $file.Name)
move-item $file -Destination $newpath
}
}
}
You could even create target folders for extensions if they do not exist yet:
$SourceFolder = C:\sample
$TargetFolder = D:\sample
Get-ChildItem -Path $SourceFolder -File |
ForEach-Object{
$DesinationFolder = Join-Path -Path $TargetFolder -ChildPath $_.Extension.TrimStart('.')
if(-not (Test-Path -Path $DesinationFolder)){
New-Item -Path $DesinationFolder -ItemType Directory | Out-Null
}
Copy-Item -Path $_.FullName -Destination $DesinationFolder -Force
}

Powershell exclude items when copying not working

I am willing to copy recursively from one dir to another by excluding some items that cause errors if copied.
It was working fine when I only had the "System Volume..." and "RECYCLE.BIN" values in "$Excluir" variable, but, now I need to exclude every item that starts with a dot "." so I wrote the loop you see after it that adds new values to the $Excluir variabl.
Now the "-Exclude" parameter forgets excluding the new values, in this case these values are names of files and directories that start with a dot "."
Sorry if my english causes confusions.
This is my code:
$RutaOrigenFicheros = "E:\"
$RutaTempFicheros = "A:\ENTRADA\TMP\"
$Excluir = #( "System Volume Information","`$RECYCLE.BIN")
$ElementosOcultosUnix = Get-ChildItem $RutaOrigenFicheros -Name -Recurse -Include ".*"
foreach ($i in $ElementosOcultosUnix){
if ($i -match "\\")
{
$elemento = $i -split "\\"
$n = ($elemento.length) - 1
$Excluir += $elemento[$n]
}
else
{
$Excluir += $i
}
}
Write-Host $Excluir
Copy-Item -Path $RutaOrigenFicheros* -Destination $RutaTempFicheros -Recurse -Force -Exclude $Excluir -ErrorAction Stop
Your logic isn't very clear (or doesn't make sense). Here's what I think you're trying to accomplish with your code:
$Destination='A:\Temp\'
$Exclude = Get-ChildItem -Path 'E:\' -Recurse -Force |
Where-Object { $_.FullName -like '*System Volume Information*' -or
$_.FullName -like '*$RECYCLE.BIN*' -or
$_.FullName -like '*\.*' }
Write-Host $Exclude.FullName
Copy-Item -Path 'E:\*' -Destination $Destination -Recurse -Force -Exclude $Exclude.FullName -ErrorAction 'Stop'

Moving Files to Folder Based on Filename

I have several thousand files in a single directory. Many of these files need to be grouped together in their own directory based off a part of the filename. I need a part of the filename to be the destination folder name. I put dashes around the part of the filename I need the directory to be named.
For instance, the following files are located in a single directory:
filea-123-.PDF
fileb-123-.PDF
filec-456-.PDF
filed-123-.PDF
file3-456-.PDF
I need all files with "-123-" to be moved to a folder called "123". Likewise, I need all files with "-456-" to be moved to a folder called "456" and so on.
Here is what I have so far:
$dir = "C:\convert"
$filelist = (Get-Item $dir).GetFiles()
foreach ($file in $filelist)
{
$newdir = $file.Name -match '-\d+-'
Move-Item $file -Destination "C:\convert\$matches[0]"
}
I've also tried this:
$dir = "C:\convert"
$filelist = (Get-Item $dir).GetFiles()
foreach ($file in $filelist)
{
$pieces = $file-split"-"
$start = $pieces.Count*-1
$folder = $pieces[$Start..-2]-join" "
$destination = "C:\convert\{0}" -f $folder
if (Test-Path $destination -PathType Container)
{
Move-Item -Path $filename -Destination $destination
}
}
Try this
$dir = "C:\convert"
$filelist = #(Get-ChildItem $dir)
ForEach ($file in $filelist){
# Gets the '123' part
$folder = $file.Name.Split("-")[1]
#Test if folder exists.
Set-Location ($dir+'\'+$folder)
#If no folder, create folder.
if(!$?){ mkdir ($dir+'\'+$folder) }
#Move item keeping same name.
Move-Item $file.FullName ($dir+'\'+$folder+'\'+$file.Name)
}
}
Use a capturing group in your regular expression for extracting the number from the filename:
Get-ChildItem $dir -File | Where-Object {
$_.Name -match '-(\d+)-.pdf$'
} | ForEach-Object {
Move-Item $_.FullName ('{0}\{1}' -f $dir, $matches[1])
}
or like this, since Move-Item can read directly from the pipeline:
Get-ChildItem $dir -File | Where-Object {
$_.Name -match '-(\d+)-.pdf$'
} | Move-Item -Destination {'{0}\{1}' -f $dir, $matches[1]}
I like Ansgars approach, If the sub folders still have to be created:
Get-ChildItem -Path $dir -Filter "*-*-.PDF" |
Where-Object Name -match '-(\d+)-.pdf$' |
ForEach-Object {
$DestDir = Join-Path $dir $matches[1]
If (!(Test-Path $DestDir)) {mkdir $DestDir|Out-Null}
$_|Move-Item -Destination $DestDir
}