Powershell to move files to folder in increments and compress each folder - batch-file

I'm trying to write a script, that will select N number of files randomly, and move them to folders named 1, 2, 3.. Then it must compress each folder, and run another batch/script.
The script I use to randomly copy N number of files, is:
gci somefolder | random -c $x | mi -dest someotherfolder
Example of what I need:
C:\somefolder (has 11000 files)
C:\1 (has 2000 files)
C:\2 (has 2000 files)
C:\3 (has 2000 files)
C:\4 (has 2000 files)
C:\5 (has 2000 files)
C:\6 (has 1000 files)
Then each folder is compressed to
C:\1.zip
C:\2.zip
C:\3.zip
C:\4.zip
C:\5.zip
C:\6.zip
And lastly, it will run a simple another batch file (Thinking of FTP'ing files)

A big thank you to //\O// for his out-zip function! This will do what you want:
function out-zip {
Param([string]$path)
if (-not $path.EndsWith('.zip')) {$path += '.zip'}
if (-not (test-path $path)) {
set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
}
$ZipFile = (new-object -com shell.application).NameSpace($path)
$input | foreach {$zipfile.CopyHere($_.fullname)}
}
$Path = "C:\Temp"
$FileList = gci $path
[int]$FilesPerZip=100
For($i=1;$i -le [Math]::Ceiling($FileList.count/$FilesPerZip);$i++){
md "c:\$($i)"
gci $path|random -Count $FilesPerZip|%{$_.moveto("c:\$i\$($_.name)")}
}
(1..[Math]::Ceiling($FileList.count/$FilesPerZip))|%{gi "c:\$_"|out-zip "C:\$_.zip"}
Just update your path and how many files you want in each zip file.
This counts how many files in total, divides by how many files you want per zip file, and rounds up. Then it loops through the target directory grabbing X files at random and placing them into sequential numbered folders. Lastly it zips those folders.
It will fail if there are already zip files with the desired name existing already (i.e. C:\1.zip), and will probably throw errors if there are those folders there as well, and will fail if there are those folders AND there are matching files in them, so you will probably want to throw in some checks up front to make sure those folders and files don't exist already, but this answers your Move & Zip question.

Related

Batch replacing text within .xml files within a zip archive through powershell

I've posted this question before, yet was not able to find a suitable solution for my problem, hence I have been testing some more myself and have some new findings and theories as to why It might not work as intended. I hope a respectable time has passed for me to bump my question with new info attached.
I am for quite a while, in my free time, tackling a script that can batch replace external link addresses in multiple excel files within script folder. I have learned, that you can't change external links via usual powershell to excel interaction, as these values are forced to read-only. However, there is a clever way to bypass that by converting the Excel file to a .zip archive and read/change the files inside and then rename it back to excel format.
Through learning and digging around the web, I have compiled this script function that should create a backup, rename to archive and then replace desired text within, renaming the file backwards afterwards.
function Update-ExcelLinks($xlsxFile, $oldText, $newText) {
# Build BAK file name
$bakFile = $xlsxFile -ireplace [regex]::Escape(".xlsb"), ".bak"
# Build ZIP file name
$zipFile = $xlsxFile -ireplace [regex]::Escape(".xlsb"), ".zip"
# Create temporary folder
$parent = [System.IO.Path]::GetTempPath();
[string] $guid = [System.Guid]::NewGuid();
$tempFolder = Join-Path $parent $guid;
New-Item -ItemType Directory -Path $tempFolder;
# Uncomment the next line to create backup before processing XLSX file
# Copy-Item $xlsxFile $bakFile
# Rename file to ZIP
Rename-Item -Path $xlsxFile -NewName $zipFile
# Not using Expand-Archive because it changes the ZIP format
C:\7z\7za.exe x "$zipFile" -o"$tempFolder"
# Replace old text with new text
$fileNames = Get-ChildItem -Path $tempFolder -Recurse -Force -Include *.xml,*.bin.rels
foreach ($file in $fileNames)
{
(Get-Content -ErrorAction SilentlyContinue $file.PSPath) |
Foreach-Object { $_ -replace $oldText, $newText } |
Set-Content $file.PSPath
}
# Changing working folder because 7Zip option -w doesn't work
Set-Location -Path $tempFolder
# Not using Compress-Archive because it changes the ZIP format
C:\7z\7za.exe u -r "$zipFile" *.*
# Rename file back to XLSB
Rename-Item -Path $zipFile -NewName $xlsxFile
}
So far, I am able to find the desired file, rename it to .zip, extract it to a temporary folder, and according to the powershell window prompts, it updates the archive with new files. Afterwards I am left with the .zip file without any desired changes inside. The files that are responsible for external links data in the excel files are located at
wk33\Gross Qty_wk33.zip\xl\externalLinks\_rels
and are presented in the form of files named externalLink1.bin.rels and numbered onwards.
These files are essentially identical to a .xml file and are opened with either Notepad or Internet explorer through windows and contain the following:
The aim of my script is to rename the week number within "Target=" parameters from last week to current (For example wk32 to wk33). The thing is that no changes happen even though no errors are displayed, and 7zip indicates that files are packed into the zip successfully.
I have tested what happens, If I unpack the .bin.rels file and change the week number inside manually through notepad and repeat the intended script process and I can confirm that it works. When I open the file the link is correctly updated.
The last 4 steps seem to be not working as intended, even though they are correct as far as I am aware. The changes are not made and the file is not consecutively renamed back to its original .xlsb extension.
Here is the output of my powershell window upon trying to execute the function:
I've been trying for several weeks to make it work, but nothing substantial can be changed as it seems. I would appreciate any additional insights or alternatives to my code to achieve the same task.
EDIT: The function is intended to be called upon from within the working directory, so it is supposed to be used as Update-ExcelLinks 'Gross Qty_wk33.xlsb' 'wk32' 'wk33' Although I have tried calling the file via its full path as Update-ExcelLinks 'C:\Test\Gross Qty_wk33.xlsb' 'wk32' 'wk33'

Using RegEx to match characters between two symbols and copy it to a location

I have directory of files and my goal is matching a 5 digit zip code and copying it to another set of specific folders.
I know there are a number of ways to do this but sometimes the zip code shows up twice in the file name so I have to match the zip code in between ^ and % such that the entire filename is like: mjn22182aguygbc^12350%abc.pdf.
Another assumption is the destination location has preset folders named the zip code such as: d:\queries\12350.
My goal is to move mjn22182aguygbc^12350%abc.pdd to d:\queries\12350 if the zip code exists in some list i can read in and if it is not part of the zip codes, the file stays in the source folder.
So far I have the following but the all files are being copied into my root destination folder and not the folders that I've created eg 12350 and I'm having trouble :
$dstpath = "D:\queries"
$filterlist = #("12350","90182")
$fileList = Get-ChildItem -Path $srcpath -Force -Recurse
foreach ($currentfile in $fileList)
{
foreach($zip in $filterLists)
{
$currentzip = $currentfile.Name -match '(?<=\^)[0-9]+(?=%)';
if($currentzip -in $filterlist)
{
Move-Item -Path $($file.FullName) -Destination $dstpath
}
}
}
The regex is right, but all -match does is return true.
'mjn22182aguygbc^12350%abc.pdd' -match '(?<=\^)[0-9]+(?=%)'
True
The match would be contained in $matches.0 afterwards.
$matches.0
12350
You're moving to $dstpath. There's no reason it would go anywhere else.

How do I copy files based on a list, into their corresponding folders which are also created based on a list?

So, I'm completely new to scripting and batch files.
I'm looking to copy files based on a list of the files to copy. I have a text file for the list of files to copy and I want the script to copy all these files line by line from a source directory.
For example I have over a 1000 files to copy, and there are 3 files for each folder I want to create and put them into. Below is an example of how the files names are formatted:
file3_AB12_autoc.pdf
file3_AB12.jpeg
file1_AB12.png
file3_CD34_autoc.pdf
file3_CD34.jpeg
file1_CD34.png
...etc...
Once these are copied, I want to move them into folders that I created using a text file and the command:
FOR /F %i in (folders_list.txt) do md %i
Now, with my script, I want to move the files it copies into their corresponding folders. Basically if the file name contains the folder name, then they should move into the folder. For example:
C:\AB12 THIS FOLDER SHOULD HAVE ALL THE FOLLOWING FILES
file3_AB12.jpeg
file3_AB12_autoc.pdf
file1_AB12.png
C:\CD34 THIS FOLDER SHOULD HAVE ALL THE FOLLOWING FILES
file3_CD34.jpeg
file3_CD34_autoc.pdf
file1_CD34.png
I have looked up other similar questions but nothing seems to work for what I want to do. I believe the links below are useful but I do not know how to put them together.
How do I copy files into folders based on the file containing the folder name?
Copy files based on a list stored in .txt file
In PowerShell, Move-Item will move the files. Then you just need regular expressions to determine the path and new file name, similar to:
$txt = "file3_AB12_autoc.pdf
file3_AB12.jpeg
file1_AB12.png
file3_CD34_autoc.pdf
file3_CD34.jpeg
file1_CD34.png
badfilename.txt"
foreach ($orig_file in $txt -split '\r\n') {
if ( $orig_file -match '^([^_]*)_([^_.]*)(.*)\.(.*)$' ) {
$dir = $matches[2]
$new_file = '{0}{1}.{2}' -f $matches[1], $matches[3], $matches[4]
'Moving {0} to {1}\{2}' -f $orig_file, $dir, $new_file
Move-Item -Path $orig_file -Destination ('{0}\{1}' -f $dir, $new_file)
}
else {
'{0} not processed' -f $orig_file
}
}

Scheduled Powershell Moves to Specific Folders

Thanks for viewing my question. I was unable to find any information online in regards to my question. I also have very basic experience in this area.
PowerShell Script:
-Query folder for files (list?)
-Move file based on filename to folder with same name. (Move with pipe to query?)
-Move will also parse second part of file name to include subsequent matching folder name for destination folder.
Files will contain many separate names so the move has to be on a loop.
Ex. File - "Name 1"
Scripts excutes moves file to folder with "name" then to subfolder "1".
Just to be clear there will be multiple names and numbers so multiple destination paths. Basically every file will have a different destination but the destination will correlate to the file name. If there is a language more accessible for this function please let me know.
Something like the following will get you started
$files = Get-ChildItem -File
foreach($f in $files) {
$dirname = $f -split " " -join "\"
New-Item -ItemType Directory -Path ".\$dirname"
Move-Item $f $dirname
}

Powershell - Copying Files to a share

This is my first post so be gentle.
I'm starting to use Powershell and found it very intuitive and would like some advice/examples on how to properly script something specific instead of just copying files from one place to another.
Files structure:
c:\backup\archive\
test_20130320_000711_backup.rar
test1_20130320_000711_backup.rar
test_20130320_001215_backup.rar
test1_20130320_001215_backup.rar
test_20130321_000811_backup.rar
test1_20130321_000811_backup.rar
test_20130321_001015_backup.rar
test1_20130321_001015_backup.rar
Unpacking directory:
c:\unpack_file\[contents of each rar goes here, one at a time]
destination:
E:\backup\archive\[date of file above e.g. 20130320 created]\[unpacked rar file contents here]
What I need to do is copy each file by date and unpack each, one at a time. Then copy the contents to the destination folder and remove whats in the unpacking folder. phew!
I've done some basic scripting but this is a real challenge so any pointers or examples would be amazing!
I am not sure why you need the intermediate directory. Here is some code to get you started.
$rarExe = "C:\Program Files (x86)\7-Zip\7z.exe"
$srcDir = "C:\backup\archive"
$dstDir = "E:\backup\archive"
$rarFiles = gci $srcDir
foreach ($file in $rarFiles){
$arcDate = $file.basename.Split("_")[1]
New-Item "$dstDir\$arcDate" -type directory
Write-Output "EXECUTING: $($startinfo.FileName) $($startinfo.Arguments)"
$startinfo = new-object System.Diagnostics.ProcessStartInfo
$startinfo.FileName = $rarExe
$startinfo.Arguments = "e $($file.fullname) -o$dstDir\$arcDate"
$process = [System.Diagnostics.Process]::Start($startinfo)
}

Resources