I received a good suggestion in another thread to support the removal/replacement of specific characters from filenames in a directory structure. Works as expected for common ascii characters (like &).
PowerShell (works fine to remove & character from filenames):
powershell.exe -c "Get-ChildItem 'c:\Media\Downloads' -Filter '*&*' -Recurse | Rename-Item -NewName {$_.name -replace '&','' }"
I also need remove single quotes from some files: Example: mark's_file.txt.
I've tried a few variants without success. I think I am running into a punctuation issue I am unable sort out. I also tried using a variable = char(39) and adding to the string. No luck.
Any ideas to accomplish?
Note: Would like a self contained batch file approach, vs calling an external .ps1 file.
A Batch file also works fine to remove both & and ' characters from filenames:
#echo off
setlocal EnableDelayedExpansion
rem Remove "&" characters:
for /R "c:\Media\Downloads" %%a in ("*&*") do (
set "fileName=%%~NXa"
ren "%%a" "!filename:&=!"
)
rem Remove "'" characters:
for /R "c:\Media\Downloads" %%a in ("*'*") do (
set "fileName=%%~NXa"
ren "%%a" "!filename:'=!"
)
... but the Batch file start run much faster than the PS one!
Related
can you show me a way to solve following problem with Powershell or CMD?
This is my file names in folder.
002.mp3
003.mp3
.
.
.
604.mp3
I want to change that numbers to;
001.mp3
002.mp3
003.mp3
.
.
.
603.mp3
But important thing is, it has to be like that
002.mp3 to 001.mp3
003.mp3 to 002.mp3
...
...
...
604.mp3 to 603.mp3
thank you very much.
You can do the following:
$files = Get-ChildItem -Path "C:\PathToMP3Files\[0-6][0-9][0-9].mp3" -File
$files | Rename-Item -NewName {"{0:D3}.mp3" -f ([int]$_.BaseName - 1)} -whatif
Just remove the -whatif parameter to perform the rename if you are satisfied with the results.
Explanation:
The -Path parameter of Get-ChildItem supports wildcards. Using a wildcard range [0-6] (one character from the set 0 to 6), you can narrow down your target items.
Since New-Item's -NewName supports delay-script binding, you can pipe your FileInfo objects directly into the command. The -NewName parameter manipulates the Name property of the object. The code above is using BaseName, which is the Name without the extension, because it is an easy way to perform digit increase.
-f is the string format operator. It performs a substitution of {number} values within a string. The number corresponds to an item's index in the collection provided to the right of the -f.
This is simpler in a Batch file, and run faster than PS too! (just try it)
#echo off
setlocal EnableDelayedExpansion
for /F %%a in ('dir /B *.mp3') do set /A "n=1%%~Na-1" & ren "%%a" "!n:~1!.mp3"
Yoy may even do it directly at the command prompt with no need of a .bat file; just be sure that n variable does not exists (executing set "n=" before):
for /F %a in ('dir /B *.mp3') do #set /A "n=1%~Na-1" & call ren "%a" "%n:~1%.mp3"
So I have files (mostly documents) with a file name beginning with "YYYYMMDD - Title of file.etc"
I'm wanting to change the date format to YYYY-MM-DD
I'm wanting to do a script to batch rename since I'll be doing this every now and then.
My bat code so far after a 2 days of research to no avail:
for %%a in ("*.*") do ren *.* ????-??-??*.*
pause
Any help or point to the right direction for me to look at would be really helpful. Thanks
final
rem // Loop through all matching files:
for /F "eol=| delims=" %%F in ('
dir /B /A:-D-H-S "*.*"
') do (
rem // Store the current file name and extension to variables:
set "NAME=%%~F"
rem // Enable delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem // Rename file by applying sub-string expansion:
ren "!NAME!" "!NAME:~,4!-!NAME:~4,2!-!NAME:~6!!EXT!"
endlocal
)
pause
You are utilising a for loop but not using its meta-variable %%a in the body then, which makes no sense.
Unfortunately, you cannot just use ren for that, because every ? in the new name represents the character of the old name at that position.
I would do it the following way:
rem // First change to the target directory:
cd /D "D:\Target\Dir"
rem // Loop through all matching files:
for /F "eol=| delims=" %%F in ('
dir /B /A:-D-H-S "*.*" ^| findstr /I "^[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]"
') do (
rem // Store the current file name and extension to variables:
set "NAME=%%~nF" & set "EXT=%%~xF"
rem // Enable delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem // Rename file by applying sub-string expansion:
ren "!NAME!!EXT!" "!NAME:~,4!-!NAME:~4,2!-!NAME:~6!!EXT!"
endlocal
)
The [findstr][cmdfnd] is used here to filter for file names that begin with eight decimal digits that could represent a date. If you do not want that simply remove everything from ^| findstr up to the end of that line.
Delayed variable expansion is needed here, because you are writing and reading variables within the same block of code. Splitting the original name at fixed character positions is done by sub-string expansion.
(How-To: Extract part of a variable (substring))
[cmdfnd]: https://ss64.com/nt/findstr.html
(FINDSTR)
RightHanded,
Maybe you should look at Powershell commands.
The following powershell command replaces spaces with underscores of all files of the current directory :
dir | rename-item -NewName {$_.name -replace " ","_"}
Source : https://www.howtogeek.com/111859/how-to-batch-rename-files-in-windows-4-ways-to-rename-multiple-files/
You can see how to modify Powershell strings here for example : https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convert-string?view=powershell-5.1
Powershell will be much easier to do this. Use this:
#echo off
pushd "The Directory"
powershell -command "& {get-childitem | foreach {$NewName = $_.Name -replace '\d{8}.*', '\d{4}-\d{2}-\d{2}.*'; rename-item -path '.\$_.Name' -newname '$NewName'}}"
popd
goto :eof
You can use this as a function to rename the files to the format you want. You can call this function inside a loop FOR, if you want.
set old_filename=YYYYMMDD - Title of file.etc
:: Extract only the first 4 characters
SET yyyy=%old_filename:~0,4%
:: Skip 4 characters and then extract the next 2
SET mm=%old_filename:~4,2%
:: Skip 6 characters and then extract the next 2
SET dd=%old_filename:~6,2%
:: Skip 8 characters and then extract everything else
SET everything_else=%old_filename:~8%
:: Rename de old filename to the new
rename "%old_filename%" "%yyyy%-%mm%-%dd%%everything_else%"
I have several thousand files with similar, but different formats, ie:
[Block 1] Thisfile.txt
[Block 1] Thisfile1.txt
[Block 1] Thisfile2.txt
[Backup001] Thatfile1.doc
[Backup001] Thatfile2.doc
[Backup001] Thatfile3.doc
[Explode] Thisplace.xls
[Explode] Thisplace1.xls
[Explode] Thisplace2.xls
I want to remove the "[text] " and keep everything else the same. Since that text varies I can't do a strict number of characters ie
set var=%1
#echo %var:~-7%
I tried to dabble with powershell commandline and tried:
dir *.xls | Rename-Item -NewName {$_.Name -replace '[Explode\s\'}
But was given the following error:
Rename-Item : The input to the script block for parameter 'NewName' failed. Invalid regular expression pattern: [Explode\s\.
At line:1 char:33
+ Dir *.xls | Rename-Item -NewName <<<< {$_.Name -replace '[Explode]\s\'}
+ CategoryInfo : InvalidArgument: (C:\1\[Explode... Thisfile1.xls:PSObject) [Rename-Item], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.RenameItemCommand
I've searched StackExchange, and the 'batch-rename' tag, and found (and tried) several similar things that I thought I could tweak, but no luck.
Here's the latest based on another StachExchange answer:
for %%F in (*.xls) do (
SET string=%%F
SET modified=!string:Explode=1!
echo !modified!
)
I was just trying to get ANY replace to work... No luck.
Your PowerShell was fairly solid, the only issue is that the square braces are reserved characters and have to be escaped with a preceding backslash. The RegEx that should work for you should be:
-replace '\[.*?\]\s*'
You can see the detailed explanation of that at this link:
https://regex101.com/r/yM6sQ9/1
Edit: Sorry, just got into work and saw your messages. I tried that regex with a test file and was able to rename it without issues. Test file created:
C:\Temp\[glarb]ThisIsATest.tst
I then ran the following line in PowerShell:
Get-ChildItem C:\Temp\*.tst | Rename-Item -NewName {$_.Name -replace "\[.*\]\s*"}
After which I looked and was left with the file:
C:\Temp\ThisIsATest.tst
I'm not sure why your code didn't work, perhaps it is a bug in your version of PowerShell. The regex and command do work in PS v4 running in Win8.1.
Using pure batch:
#echo off
for /f "delims=" %%F in (
'dir /b /a-d [*]*'
) do for /f "tokens=1* delims=]" %%A in (
"%%F"
) do for /f "tokens=*" %%C in ("%%B") do ren "%%F" "%%C"
Using my JREN.BAT regular expression renaming utility, a pure script utility (hybrid JScript/batch) that runs natively on any Windows machine from XP onward:
call jren "^\[.*?] *" "" /fm "[*]*"
You can drop the CALL if you use the command directly from the command line.
My RegEx-Foo is not very strong (it's on the to-do list), but you should be able to do this with a sub string.
dir *.xls | Rename-Item -NewName { ($_.Name.Substring($_.Name.IndexOf(']') + 1)).Trim() }
Looking a little closer at what actually changed, we're returning a sub string of $_.Name which is from the index after the first ']' character and then also trims the output, dealing with any extra white spaces (namely spaces).
This has the obvious limitation of not working for files that are in the form of:
this[should]notBeEdited.xls
In a batch file I need to change, within a file, all instances of ##token## (just my own placeholder) with the value of a variable from earlier in the script (%tokenvar%), and output the result to a file. From an answer on here I came up with calling powershell:
type file.json|powershell -Command "$input|ForEach-Object{ $_ -replace \"##token##\", \"%tokenvar%\" }" > file.2.json
The problem is that the resultant file is wrapped at 80 chars which I need it not to be!
How can I do this?
You don't need to use Out-String in this case as Out-File has a Width parameter as well:
... | Out-File File.2.json -Width 300"
Just make sure the | Out-File ... is part of the PowerShell command.
The problem is that the redirection operator in PowerShell (>) will turn into Out-File with a width of 80 characters. You can use Out-File with an arbitrarily large width (I prefer 10k), or pipe to Set-Content (which will be slower). You can also assign the result into a variable, and use [IO.File]::WriteAllText to perform the update.
You can do that directly in your Batch file with no need of Powershell:
#echo off
setlocal DisableDelayedExpansion
for /F "delims=" %%a in (file.json) do (
set "line=%%a"
setlocal EnableDelayedExpansion
echo !line:##token##=%tokenvar%!
endlocal
)
This Batch file assume that there is not empty lines in file.json and that the value of %tokenvar% have not special Batch characters. These two points may be fixed, if needed.
My text file contents similar to following lines
xcopy Source Destination /y /r /Q
xcopy Source Destination /y /r
I am trying to remove all the characters after Desination.
I was trying with Indexof method and remove method. But i did not find a right answer
I tried the find the third occurence of Whitespace and remove from it. but it doesn't works.
$index=$line.IndexOf(" ",3)
$line=$line.RemoveAt($index)
Can some one helps me to achieve this using powershell
I'm guessing your actual file will have paths such as this:
xcopy "C:\Folder with space" "C:\Folder 2 with space" /y /r /Q
So you can remove the xcopy arguments with a search/replace regular expression such as this:
'xcopy "C:\Folder with space" "C:\Folder 2 with space" /y /r /Q' -replace '/[\w]' , ''
The result is:
xcopy "C:\Folder with space" "C:\Folder 2 with space"
This way you don't have to worry about how many spaces are before the xcopy parameters. The parameters will be removed regardless of how many spaces came before them.
The regular expression matches and removes text with a forward slash followed by a character class representing a word character.
[Regex]::Replace("xcopy Source Destination /y /r /Q","^(xcopy) +([^ ]+) +([^ ]+).*$","`$1 `$2 `$3") should do the trick.