Powershell Move file from directory to subdirectory based on filename - regex

I would like to do all 8k+ files at once using the pattern since the left 5 chars of the file matches the right 5 of the sub-directory to move to.
This works one by one:
move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- 05165";
move-item -path X:\"Property Files"\05164*.pdf -destination X:\"Property Files"\"* -- 05164";
Thank you in advance for any help.

As a one-liner, assuming destination folder already exist:
Get-ChildItem "X:\Property Files\*.PDF" |
ForEach { move -path $_ -destination ($_.directoryname +"\* -- "+ $_.Name.substring(0,5))}
Using only the filename, you just extract the first five chars (substring(0,5)), then use it as the end of the folder to match.
$_.Directoryname assume destination folder is a subfolder of the source path.

Ok, you're on the right path with the whole RegEx tag here. What I did is look for everything until the last backslash, then captured 5 digits, then everything that isn't a backslash until the end of the line, and only returned the captured group. I set that as a variable $ItemNumber, and used that in the destination. I ran that on a ForEach loop for everything in the target source folder. Here's the code I ended up with:
ForEach($File in (GCI "X:\Property Files\*.PDF")){
$ItemNumber = $File.Fullname -replace ".+?\\(\d{5})[^\\]*$", "`$1"
move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- $ItemNumber"
}
You could do it through the pipe if you wanted, like this:
GCI "X:\Property Files\*.PDF"|%{move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- $($_.Fullname -replace ".+?\\(\d{5})[^\\]*$", "`$1")"}
But that gets kind of long, and some people really don't like that long of a single line.
That RegEx can be tested here, plus it breaks it all down. (link to regex101.com explanation)

Related

Add leading zero to file names using PowerShell

I have a folder that contains multiple hunderd .mp3-files, all with the same name and an ascending number. The filenames look like this:
Test 01.mp3
Test 02.mp3
Test 03.mp3
Test 100.mp3
Test 101.mp3
Test 102.mp3
As you can see, the number of leading zeros in the first files is wrong, as they should have one more. I'd like to use PowerShell to solve the problem as I am currently learning to operate this quite helpful tool.
I tried to count the digits in the file names using the Replace Operator to filter out any non-digit characters. I assumed that the first 99 files would have three digits while the other files would have more (counting the '3' of the .mp3 file extension)
Get-Childitem | Where {($_.Name.Replace("\D","")).Length -le 3}
That should give me any files that have 3 or less digits in their file name - but it doesnt. In fact, it shows none. If i increase the number at he end to 11, i get the first three test files, increasing it to 12 shows all six of them. I assume that the Replace-Operator doesn't get applied to the file name before the filtering based on the Length-Operator, although I used brackets around $_.Name.Replace("\D","")
What the hell am I doing wrong?
I figures it out: Get-ChildItem | Where {($_.Name -replace "\D","").Length -le 3} returns the files that I need to rename.
The whole command I used was
Get-ChildItem | Where {($_.Name -replace "\D","").Length -le 3} | Rename-Item -NewName { $_.Name -replace "Test ","Test 0"}
Its also possible to rename all files to an number-only scheamtic and use the padleft command as shown here
By replacing "Test " with "Test 0", you would still not achieve what you want on files that are numbered Test 1.mp3 (as this will become Test 01.mp3, which is one leading zero short).
You can make sure all files will have a 3-digit sequence number by doing this:
Get-Childitem -Path 'D:\Test' -Filter '*.mp3' -File |
Where-Object {$_.BaseName -match '(\D+)(\d+)$'} |
Rename-Item -NewName { '{0}{1:D3}{2}' -f $Matches[1], [int]$Matches[2], $_.Extension }
With this, also wrongly named files like Test 00000003.mp3 wil be renamed as Test 003.mp3

Comparing two text files is not working in Powershell

I am trying to compare the contents of two text files and have only the differences be outputted to the console.
The first text file is based on the file names in a folder.
$AsyFolder = Get-ChildItem -Path .\asy-data -Name
I then remove the prefix of the file name that is set up by the user and is the same for every file and is separated from the relevant info with a dash.
$AsyFolder| ForEach-Object{$_.Split("-").Replace("$Prefix", "")} | Where-Object {$_}|Set-Content -Path .\templog.txt
The output looks like $Asyfolder Output
bpm.art
gbr.pdf
asy.pdf
fab.pdf
as1.art
odb.tgz
ccam.cad
read_me_asy.txt
There is another file that is the reference and contains the suffixes of files that should be there.
It looks like this Reference File
tpm.art
bpm.art
gbr.pdf
asy.pdf
fab.pdf
as1.art
as2.art
odb.tgz
xyp.txt
ccam.cad
And its contents are received with $AsyTemplate = Get-Content -Path C:\Users\asy_files.txt
The logic is as follows
$AsyTemplate |
ForEach-Object{
If(Select-String -Path .\templog.txt -Pattern $_ -NotMatch -Quiet){
Write-Host "$($_)"
}
}
I have tried various ways of setting up the templog.txt with -InputObject: using Get-Content, Get-Content -Raw, a variable, writing an array manually. I have also tried removing -NotMatch and using -eq $False for the output of select string.
Everytime though the output is just the contents of asy_files.txt (Reference File). It doesn't seem to care what is in templog.txt ($AsyFolder Output).
I have tried using compare-object/where-object method as well and it just says that both files are completely different.
Thank you #Lee_Dailey for your help in figuring out how to properly ask a question...
It ended up being additional whitespace (3 tabs) after the characters in the reference file asy_files.txt.
It was an artifact from where I copied from, and powershell was seeing "as2.art" and "as2.art " I am not 100% as to why that matters, but I found that sorting for any whitespace with /S that appears after a word character /W and removing it made the comparison logic work. The Compare-Object|Where-Object worked as well after removing the whitespace.

How to robocopy using regex matched folder from one server to another

I've a build system which uses robocopy to copy files from one system to our server, and to a specific path. The following has worked well till a new requirement was introduced:
robocopy local\dist \\server01\somepath\dist XF *.* /E
Now, we want to have a changing 'dist' name to include build information. For example, 'dist1', 'dist2', 'distabcd'. Anyhow, the point is, that the folder name is changing. How do I tell robocopy to match on any name beginning with 'dist', but copy to the correct full named dist folder on the remote server
robocopy local\dist* \\server01\somepath\[????] XF *.* /E
I have the option to use PowerShell commands to do this, assuming it may be able to copy to the server location. I know almost nothing about PowerShell, but welcome any tips.
Powershell provides RegEx functionality with the '-match' and '-contains' operators. Here would be an example of what capturing changing directories would look like:
$localDirectory = "local\dist"
$directory = "\\server01\somepath\dist"
$keyword = "dist"
$fileDirectory = Get-ChildItem -Path $directory -Recurse
foreach ($container in $fileDirectory)
{
# -match is one of the RegEx functions we may utilize for this operation
# e.g dist1.. dist2.. distabc.. adist.. mynewdistrubition
if ($container -match $keyword)
{
try
{
Copy-Item -Path "$($directory)\$($container)" -Destination $localDirectory -Force -Recurse
}
catch [System.Exception]
{
Write-Output $_.Exception
}
}
}

Batch rename files with regex

I have a number of files with the following format:
name_name<number><number>[TIF<11 numbers>].jpg
e.g. john_sam01 [TIF 15355474840].jpg
And I would like to remove the [TIF 15355474840] from all of these files
This includes a leading space before the '[TIF...' and a different combination of 11 numbers each time.
So the previous example would become:
josh_sam01.jpg
In short, using powershell (or cmd.exe) with regex I would like to turn this filename:
josh_sam01 [TIF 15355474840].jpg
Into this:
josh_sam01.jpg
With variables being: 'john' 'sam' two numbers and the numbers after TIF.
Something like, with added newlines for clarity:
dir ‹parameters to select the set of files› |
% {
$newName = $_.Name -replace '\s\[TIF \d+\]',''
rename-item -newname $newName -literalPath $_.Fullname
}
Almost certainly adding -whatif to the rename until I was sure I had the file selection and rename correct.

Changing directory to a folder matching a regex in powershell

I want to CD into a folder that begins with the word "Patch", followed by several other digits. All I care about is that it begins with the word "Patch"
How can I change my directory using a regex in powershell?
This is what I have at the moment and it doesn't work. Am I on the right track though?
$FolderPath = "^Patch[0-9]+$"
cd "C:\Test\" + $FolderPath
To put you in the right direction:
Use Get-ChildItem and only get the directories matching your regex, something like:
$matchingItem = Get-ChildItem "C:\Test" -Directory | ?{ $_.Name -match $FolderPath } | select -First 1
Now you can cd to the matching directory.
You don't really need the regex. Wildcard blobbing will handle that:
cd c:\test\patch[0-9]*