Remove some characters from filename using powershell - file

I have a 100 files Which are named for instance: (Without quotes)
"Managing and Improving Own Learning [L3] {CBA849}" and
"Note-taking and Note-making [L3] {CBA851}"
I would like to rename it in a such way that it only shows "CBA849" and "CBA851" and remove anything else.
Another words I would like to keep file code inside {....} curly brackets.
Is there a way we can implement this? (Note: It's not replacing characters)
Thanks

Rename-Item -LiteralPath $path ([regex]::match($path, '{(.+)}')).Groups[1].Value
You need -LiteralPath because the filename contains brackets.
[regex]::match($path, '{(.+)}') matches the curly braces and their contents, and captures the contents into a match group. .Groups[1].Value returns the value of the first (and in this case, the only) match group.
This assumes that all the files are named in the format shown in the question. If it's possible that there might be curly braces elsewhere in the name, change the regex {(.+)} to {(.+?)}$.

I'd personally use a Regex match:
GCI $path | ?{$_.Name -match "(?:.*?{)(.*?)(?:})(\..*)?$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($matches[2])")}
Edit: As Adi Inbar says, I have created an overly complicated RegEx pattern. Simplified as he suggested (though still allowing for extensions) is a revised answer:
GCI $path | ?{$_.BaseName -match "{(.*?)}$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($_.Extension)")}
Edit: Ok, here's the breakdown...
GCI is short for Get-ChildItem, it pulls a listing of the directory specified, but I think you probably figured that one out.
Then it pipes to a Where{} clause(? is an alias for Where). It matches the BaseName of the files and folders provided by the GCI command. The BaseName property is actually one generated by PowerShell that takes the name of the file, extension and all, and then removes the extension (with preceding period) from it so if the file name is Sample.txt then it provides you with Sample as the BaseName.
It matches that against a RegEx (short for Regular Expression) pattern. If you don't know what RegEx is, please feel free to look it up and read up on it (Google is your friend). The basics is that it matches a pattern instead of actual text. In this case the pattern is anything at the end of the file name that is between curly braces.
Past that it enters a ForEach loop (I used the % alias for ForEach). For each file that matched the RegEx pattern it performs the MoveTo() method for that file. The location that it is moving it to is that file's current directory (gotten with $.Directory), followed by a backslash, followed by $Matches[1] (I'll get to that in a second), and then the original extension of the file (gotten with $.Extension). Now you'll see I wrapped the Directory and Extension in a sub-expression $() because with string extrapolation (how it auto-magically expands variables if you put them within double quotes) if you try to specify a property of a variable you have to put it in a sub-expression. Otherwise it tries to expand just the variable itself, and shows the .Whatever property name in plain text.
Lastly, $Matches is an automatic variable that is populated when you make a match with a few things (such as <something> -match <something else> like we did in the Where clause). The first record of it is the whole string that was matched <something>, and then the next records are the matches based on <something else>.
I hope that clears it all up for you. If you have specific questions let me know. If this answer resolved your question please mark it as accepted.

$f=gi $filepath;
$f.MoveTo($f.fullname.Replace($f.name,$f.name.substring($f.name.indexof("{")+1,($f.name.indexof("}")-1)-$f.name.indexof("{"))+$f.extension))
Get the File you're looking to rename as a [System.IO.FileInfo] object using get-item (gi).
Once you have the file object in $f the script is doing:
MoveTo
$f.FullName: The full path of the existing file (C:\some\dir\Test {ABC123}.txt)
Modify FullName to be the new filename by using the Replace function to replace the old filename ($f.name), with the desired name
The Substring function of the filename will allow you to get just the string between the curly braces.
Find the index of the OpenCurlyBracket within the name string
Find the index of the CloseCurlyBracket within the name string
Once the text between the curly brackets is identified with the Substring function, append the file extension to the new filename

Related

Parsing non-standard files for text using PowerShell and Select-String

Microsoft Remote Desktop saved sessions have values in them when you open them with a text editor (to test yourself, open Remote Desktop Connection, click Options, and then click Save As. Open the resulting .rdp file in a text editor).
However, using the standard Select-String command here (which works when exactly the same syntax on other file formats):
$MyOObject."Prompt" = (Select-String -Path $Path -Pattern "promptcredentialonce: (.*)").Matches.Groups[1].Value
... produces the following error:
Cannot index a null array
Is there a different command to use to parse this kind of file, or any non standard text file, in PowerShell 2.0?
Your pattern is incorrect. The syntax of the options in .rdp files is
name:type:value
In your case:
promptcredentialonce:i:0
However, you're trying to match something with a space after the option name (which doesn't exist):
promptcredentialonce: (.*)
Without a match the .Matches property is empty and .Group[1] attempts an indexed access on a null value.
If you want the value including the type, remove the space:
promptcredentialonce:(.*)
If you want just the value, change the pattern to something like this:
promptcredentialonce:\w+:(.*)

How to copy a freshly created array containing files to another folder on the same computer

I am new to Powershell but have had experience with various programming languages including dBase III, basic, Fortran (shows my age). I am a musician and launch MP3 files as an accompanyment when I perform live, somewhat like karaoke. I have about 45 different MP3s that I use. I like to change the sequence of the songs that I perform, from time to time and this requires renaming the MP3 file names with a preceeding sequence number. The file names take on the form: "01 songnameA.mp3", "02 songnameB.mp3", "03 songnameC.mp3", etc. I also repeat songs so there might be an "09 songnameA.mp3" in the folder that I play back from. To do this, I typically create a text file that lists the songs in the order that I want to perform them. Each line in the text file has the form "01 Songname X" but no MP3 extension. I then manually copy the mp3 files into a folder and then edit the names applying a sequence number according to the text file. This is time-consuming.
I have created a Powershell script (version 2) that creates an array of the text file content and an array of the unnumbered MP3 song files. The script creates a 3rd array containing numbered MP3 filenames according to the sequence in the text file. This array does work and I can easily display the list of items in it which have the form "01 SongnameX.mp3". However, I have been unable to copy this array of MP3 filenames with a preceeding sequence number into another folder. I don't know how many variations of the "Copy-Item" statements I have tried but nothing works. The name of the array that contains the filenames is $nsfarray (new song file array). The command I am presently using:
$nsfarray | copy-item -Destination C:\temp
Returns the following error message:
Copy-item : Cannot find path 'C:\Users\My HP\Documents\My Scripts\01 A Good Time.mp3' because it does not exist.
The path is the default path that I use to run Powershell but somehow the MP3 file names get appended to it. The "01 A Good Time.mp3" is the first item in the $nsfarray. I know I am missing something here. Any suggestions would be appreciated.
This is really crude but the issue I see with your input file is that it obviously does not exactly match the real file name that you are looking to copy. So with that in mind lets try this on for size.
$musicPath = "c:\music"
$destinationPath = "c:\songset"
$nsfarray = "01 Age of Aquarius"
$nsfarray | ForEach-Object{
If($_ -match '^\d+ *(?<BaseName>.*)'){
Copy-Item "$musicPath\$($Matches.BaseName).mp3" -Destination "$_.mp3"
}
}
Work with explicit paths: $musicPath and $destinationPath so that we do not have to rely on our current location in PowerShell. Then we navigate each value in the array, which I have populated with one example. Now we need to extract the real file name away from your set list number. Using regex we return the part of the string that is not the beginning numbers and spaces and take everything after that.
After we simply copy the file that exists in the $musicPath folder that has the name "Age of Aquarius.mp3", which should be the real file, and copy it to the $destinationPath as "01 Age of Aquarius.mp3", which is how you want the file for your gig.
Clarification
After answering this and looking back at the question I think there is a chance I didn't understand it right. Please update the question if this is not the right way to address this. The core of your problem, if nothing else, is that you are not specifying a proper file path for the mp3s. You need to use the proper source folder and append the mp3 to the string.

How to remove specific characters from a file name?

I have bunch of files that need to have a (.) dot removed from the file-name. Eg. "Mr.-John-Smith.jpg" to "Mr-John-Smith.jpg". I don't have real experience with programming and know only html/css and a little javascript. I found another identical question here on stackoverflow, but what I gathered it was fixed on linux system and BASH was used.
Anyways, if anyone could provide me a tutorial on which program to use for this and what code to execute in that program to make it happen I'd be grateful.
if you are using a windows environment (which i guess you do)
you can download this free utility to mass change file names !
main page :
http://www.bulkrenameutility.co.uk/Main_Intro.php
download page :
http://www.bulkrenameutility.co.uk/Download.php
its easy to use
enjoy
If your file names in a file...
1- Open Microsoft Word or any text editor. Press ctrl+h and then search "." without quotes then replace it with blank character.
2- It will remove all dots, again bring "." to your file extention such as .jpg , .png searh your file extention for example "jpg" and replace it with ".jpg"
It will works %100, i am using this method everytime.
if they are not in a file and if you want do somethings in your operation systems' file system
Try this program. It is very useful for this operation;
Download
To remove all except the extension dot from all files in a directory, you can use PowerShell that comes with newer versions of Windows, and can be downloaded for older versions;
Line breaks inserted for readability, this should go on one line;
PS> dir | rename-item -newname {
[System.IO.Path]::GetFileNameWithoutExtension($_.name).Replace(".","") +
[System.IO.Path]::GetExtension($_.name); }
What it does is to take the file name without an extension and remove all dots in it, and then add back the extension. It then renames the file to the resulting name.
This will change for example do.it.now to doit.now, or in your case, Mr.-John-Smith.jpg to Mr-John-Smith.jpg.

How to automatically remove the file extension in a file name

I am trying to make a script in bash that requires the removal of the the file extension from a file name, like the following
original: something.zip
removed version: something
And I was thinking I could use cut for this, but I am worried that a situation could arise where there might be a file name that has more than one period, etc, something similar to the following
something.v2.zip
having said that, I was wondering if anyone had any recommendations as to what I could do to just remove the last period and the text after it from a line of text/filename? any help would be appreciated, thanks!
f=file.zip
echo "${f%.zip}"
file
The '%' is a parameter modifier, it means, delete from the right side of the value of the variable whatever is after the '%' char, in this case, the string .zip. You can make this more general to remove any trailing extension, by using a wild card like
echo "${f%.*}"
file
If you want to remove the from the last period to the end, try this:
$ f=some.thing.zip
$ echo "${f%.*}"
some.thing

filename contains space and wildcard in a variable

I receive files which names contain spaces and change every week (the name contains the week number)
IE, the file for this week looks like This is the file - w37.csv
I have to write a script to take this file into account.
I didn't succeed in writing this script.
If I do :
$FILE="This is the file - w*.csv"
I don't find /dir/${FILE}
I tried "This\ is\ the\ file - w*.csv"
I tried /dir/"${FILE}" and "/dir/${FILE}"
But I still can't find my file
It looks like the space in the name needs the variable to be double-quoted but, then, the wildcard is not analysed.
Do you have an idea (or THE answer)?
Regards,
Olivier
echo /dir/"This is the file - w"*.csv
or — you almost tried that —
echo /dir/This\ is\ the\ file\ -\ w*.csv
Use a bash array
v=( /dir/This\ is\ the\ file - w*.csv )
If there is guaranteed to be only one matching file, you can just expand $v. Otherwise, you can get the full list of matching files by expanding as
"${v[#]}"
or individual matches using
"${v[0]", "${v[1]}", etc
First of all, you should not use the dollar sign in an assignment.
Moreover, wildcard expansion is not called in an assignment. You can use process substitution for example, though:
FILE=$(echo 'This is the file - w'*.csv)
Note that the wildcard itself is not included in the quotes. Quotes prevent wildcard expansion.

Resources