I am trying to rename multiple files in windows using powershell.
And I want to rename replacing this pattern:
"123456-the_other_part_of_the_string".
Example:
409873-doc1.txt
378234-doc2.txt
1230-doc3.txt
Basically I want to crop the numbers + '-' thing.
$variable -replace "^\d+-", ""
Get-ChildItem . *.txt | Where {$_.Name -match '^\d+-(.*)'} |
Rename-Item -NewName {$matches[1]}
or with aliases:
gci . *.txt | ?{$_.Name -match '^\d+-(.*)'} | rni -new {$matches[1]}
[0-9]*?-[^.]*
I'd recommend you take some time to learn regex, though, instead of just using answers from SO. You will run into all sorts of unusual file naming that may throw your program off in the real world and you woln't be able to fix these issues without understanding regex.
EDIT: Not sure if you also want to remove the 'name' part. If not, use this instead:
[0-9]*?-
Related
sorry i really dont know how to properly ask this question.
I would like to parse CS:GO Demo files in Powershell, and i would like to retrive the map name from it.
I opening dem files like this:
Get-Content $demo | Select -First 1 | Select-String -Pattern 'de_'
And i get this as response:
HL2DEMO đ5 MatchServer I.
GOTV Demo
de_mirage
csgo
##A g uÔ ~ř˙˙
ą Vđk (8wEÄü€ŢMĐhZăU X#`śh u <zcsgo‚ de_mirageŠ ’sky_dustšGOTV¨ ° ¸ ( 0 ž
I would like to get only the de_mirage as a variable. So if a map changes, then it will be de_dust2 or de_inferno and so on. Does anybody know a solution for this?
Thank you!
When using Get-Content, each line is passed down the pipeline one at a time, unless specifying the -Raw switch. The reason I bring this up is due to your Select cmdlet that you're piping to. When you specified the parameter of -First, with a value of 1, you're only grabbing the first line, and then trying to find the pattern in the first line.
Here's my poor attempt at RegEx:
Get-Content -Path $demo | Where-Object -FilterScript { $_ -match 'de_\w+' }
$Matches[0]
. . .where the $Matches Automatic Variable contains all the matched RegEx patterns (as the name indicates) stored in an array format; where we use the index number to reference the value. This would also work piping to Select-String when searching for a Pattern just like you had done.
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
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.
I have a script I wrote in my company for clearing Citrix UPM profiles. Not very complicated, but it generates logs for every user it is run on. Along the format of:
UPMreset-e0155555-20150112-0733
UPMreset-n9978524-20150114-1128
UPMreset-jsmith-20150113-0840
etc.
So I want to grab the folder with all the .txt files, select only the username and count to see if one appears more than a certain number of times. To check for problem children. Putting them into an array is easy enough, but when doing a -split I can't seem to find a regex combination to select only the username. I thought I could just do a ('-')[1], but that doesn't appear to work. Do you have any suggestions?
$arrFiles = Get-Childitem "c:\logs"
$arrFiles | %{ $arrfile = $_ -split ('-'); Write-Host $arrfile[0]}
edit: Included test code for posterity sake.
I'd try something like this:
$Path = 'N:\Folder\*.txt';
Get-ChildItem $Path |
ForEach-Object {
Write-Output $_.BaseName.Split('-')[1];
} |
Group-Object |
Where-Object { $_.Count -gt 1 } |
Sort-Object -Property Name |
Select-Object Name, Count;
To answer the question.
$_ is one of the objects returned by Get-ChildItem. Those objects are not strings. They're .Net objects of type System.IO.DirectoryInfo or System.IO.FileInfo. That means if we use $_, we're referencing the whole object. Worse, neither of those objects has a Split() method, so $_.Split('-') would refer to a function that didn't exist.
BaseName is a property of a FileInfo or DirectoryInfo object. That property contains the name of the file without the path or the extension. Critically, this property is also a String, which does have the Split() method. So using this property does two things: It removes the path name and the extension since we don't care about that and we don't want it to potentially break something (e.g., if someone put a dash in the parent folder's name), and it gives us a String object which we can manipulate with String methods and do things like call the Split function.
Try something like this at the command line:
$x = Get-ChildItem 'N:\Folder\UPMreset-e0155555-20150112-0733.txt';
$x | Get-Member;
You'll get a huge list of Methods (functions) that the object can do and Properties (attribute values) of the object. Name, FullName, BaseName, and Extension are all very common properties to use. You should also see NoteProperties and CodeProperties, which are added by the PowerShell provider to make using them easier (they wouldn't be available in a C# program). The definition tells you how to call the method or what the type of the property is and what you can do with it. You can usually Google and find MSDN documentation for how to use them, although it's not always the easiest way to do things.
Compare the above to this:
$x.BaseName | Get-Member;
You can see that it's a String, that there all kinds of methods like Split, Replace, IndexOf, etc.
Another helpful one is:
$x | Select-Object *;
This returns all the Propety, NoteProperty, and CodeProperty values this object has.
This highlights one of the best ways to learn about what you can do with an object. Pipe it to Get-Member, and you learn the type and any methods or properties that you can access. That, combined with piping something to Select-Object *, can tell you a lot about what you're working with.
What problem were you having with .split('-')[1]?
$filenames = #(
'UPMreset-e0155555-20150112-0733',
'UPMreset-n9978524-20150114-1128',
'UPMreset-jsmith-20150113-0840'
)
$filenames |% {$_.split('-')[1]}
e0155555
n9978524
jsmith
It looks like the filenames are always UPMreset-, followed by the username. So use this:
UPMreset-(.+?)-
and the capture group will contain the username. It's using a lazy quantifier to get anything up to the next dash.
You could also do the split in a calculated property with Group-Object:
$FileNames = Get-ChildItem -Path $LogDir -Filter "*.txt" -Name
$FileNames | Group-Object #{Expression={($_ -split "-")[1]}} | Where-Object {$_.Count -gt 1}
I have about 1400 images like this.
101018-202x300.jpg
100116-215x300.jpg
1000748-300x157.jpg
100138-196x300.jpg
100308-companion-in-surgical-studies-208x300.jpg
100463-Ambroise-Pare-300x216.jpg
100523-Grulee-collection-pediatrics-194x300.jpg
I need to strip out all the character after the FIRST dash so that it reads like this
101018.jpg
100116.jpg
1000748.jpg
100138.jpg
100308.jpg
100463.jpg
100523.jpg
I know this can be done with Regular Expressions but I have not a clue where to begin with it?
I am busy working through this Regex Site to learn more about the topic.
Thank you.
EDIT: Apologies, I did not add some of the other more varying examples.
You can rename capturing the 101018 and rename the file that you used. NEW (Demo)
OLD (Demo)
(\d+)[\w-]+\.jpg
EDIT: A second option is splitting by "-" and getting the first parameter.
In PowerShell:
$_ -replace '-.*(?=\.\w+$)'
e.g.
PS> -split'101018-202x300.jpg
>> 100116-215x300.jpg
>> 1000748-300x157.jpg
>> 100138-196x300.jpg' | %{ $_ -replace '-.*(?=\.\w+$)'}
>>
101018.jpg
100116.jpg
1000748.jpg
100138.jpg
You can simplify the regex a bit if you only have JPEGs or it's always the part between a hyphen-minus and a dot:
-[^.]+
Using shell and sed..
for i in $(ls /path/to/your/images)
do
mv $i $(echo $i | sed -r 's/([0-9]\*)\-.*\.jpg/\1.jpg/g')
done
Let me explain what this will do.
for loop will take one file for each iteration
echo $i | sed -r 's/([0-9]*)\-.*\.jpg/\1.jpg/g' is for changing file names to your desired output.