How to rename files, removing all characters between certain values - batch-file

I have a list of 15.000 documents where I need to remove a certain piece of text from the name.
The name structure is always: [xxx]_(xxx)_xxx.extension
I am trying to remove the (xxx)_ part of the filename. The length of xxx is variable.
I've only found ways to replace certain pieces of text or remove fixed pieces of text. Any help or guidelines are appreciated.

I would use JREN.BAT - a regular expression renaming utility. JREN.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.
Assuming you have JREN.BAT in a folder that resides within your PATH, then all you need is the following command from the command line:
jren "^(\[.*?\]_)\(.*?\)_" "$1"
The command looks for file names in the current directory that begin with [*]_(*)_ and removes the (*)_ portion.
Use CALL JREN if you put the command in a batch script.
You can add the /P option to specify a path different than the current directory, and the /S option to iterate all sub-directories.
You can use jren /?? to access the extensive documentation. Press <Enter> to advance the help one line at a time, or <space> to advance one screen page at a time. Or use jren /? to get the entire help dumped to screen immediately.

that's a job for for:
for /f "tokens=1,2,* delims=_" %%a in ('dir /b "[*]_(*)_*.extension"') do #echo %%a_%%c [removed "%%b"]
How it works:
it disassembles your filenames into three parts, based on a delimiter (_ here): firstpart_secondpart_thirdpart, then reassembling it by mounting the first and third part together.
If you want to rename them (for example), instead of just echoing, you can do: ren "%%a_%%b_%%c" "%%a_%%c"

If you want to trim multiple file names, you can try this using PowerShell.
1. Navigate to the directory where the files to rename are.
2. Excecute the following command.
dir | Rename-Item -NewName {$_.name.substring(0,$_.BaseName.length-N) + $_.Extension}
where N in "length-N" is the number of characters you want to trim, from the last one, without counting the extension file.
Example:
I restored my files after a backup in Windows 10 and every document appeared with some extra characters, showing the day and time when I made the back up.
being FileName (2020_02_13 12_33_22 UTC).extension, I needed to trim everything between the parenthesis and take FileName.extension
So I have to trim 26 characters in every filename. Then N = 26
1) I open PowerShell and navigate to the folder where I will excecute the script.
2) I excecute the following script
dir | Rename-Item -NewName {$_.name.substring(0,$_.BaseName.length-26) + $_.Extension}
Take care using this command, because it doesn't follow any parameters except to trim a given number of characters.

Related

Use content of a file in a string

I have a file (let's call it version.txt) that contains a version number and some text:
v5.02
Some text explaining
where and how this
number is used
Based on this answer, I use
set /p version=<version.txt
to store the first line of the file in the version variable. Now I'm trying to write a batch script that operates on folders that contain this version number in their name. However, I get unexpected results because something seems to go wrong when I insert the variable in a path. For example, this script
#set /p version=<version.txt
#echo C:\some\folder\%version%\some\file.exe
prints
C:\some\folder\v5.02
instead of
C:\some\folder\v5.02\some\file.exe
What's going on? I have a feeling there are hidden characters of some sort at the end of the text in the variable, because setting the variable by hand to a constant in the script works.
Edit: I'm using Windows 10 with Notepad++ as my editor, if it helps.
I can only replicate your issue, when version.txt uses Unix line endings (LF) instead of Windows (CRLF). for /f is immune to this issue:
for /f "delims=" %%a in (version.txt) do set "verion=%%a" & goto :skip
:skip
echo C:\some\folder\%version%\some\file.exe
goto :skip breaks the loop after reading the first line.
Since everything I tried didn't seem to work, the solution I found in the end is to call the batch script from a Python script. The Python script reads the first line of the version file and passes it as an argument to the batch script. Out of context, it is a bit of an inelegant solution, but in my case the batch script was already called by a Python script, so it's not that terrible.
Here is a minimal example:
version.txt
v5.02
Some text explaining
where and how this
number is used
script.bat
#echo C:\some\folder\release\%1\some\file.exe
script.py
import os
with open("version.txt") as f:
version = f.readline().rstrip()
os.system("cmd /c script.bat %s" % version)
Edit: Following Stephan's comment, I tried to change the line ending in the text file from LF to CRLF and it indeed solves the problem. However, since I don't really have control over everything that writes in that file, the solution above remains the most feasible in my case.
Edit 2: Stephan's answer (with the for loop) is actually a better solution than this one since it avoids having to transfer part of the work to the calling Python script.

How to edit/delete an entire section or just a line from an initialization file with script?

I have been tasked to edit multiple configuration files on my company's proprietary software (Windows OS). These configuration files are in INI file format (config.ini) which structures are composed of sections, properties, and values. The requirement is to:
Search for the section name and remove all corresponding properties on config.ini file.
Example: Remove entire section [RegistryService] and its properties.
[DummyProcessor]
CCLTsVersion=112
ETransformsDescription=
ETransformsVersion=0.0.0.0
LWTs=21.10.25
Transform=10.2.2.0
[RegistryService]
LoadRegistry=1
Delete an entry from a different configuration file (not limited to section):
Example: Delete just line with LoadRegistryManager=1 entry from:
[DummyService]
InitInstructions=0
ESAPsVersion=
ESVersion=10.2
LoadRegistryManager=1
Can I use Windows command line batch scripting to make these edits?
Please provide an example. I am more comfortable with Linux commands and not as privy to Windows batch scripting aside of creating/deleting files and folders.
The question How can you find and replace text in a file using the Windows command-line environment? has lots of answers. One of those answers links to JREPL.BAT written by Dave Benham which is a batch file / JScript hybrid making it possible to use regular expressions as supported by JScript from Windows command line.
The requirements can be fulfilled with jrepl.bat and following batch file both stored together in same directory:
#echo off
call "%~dp0jrepl.bat" "^\[RegistryService\][^[]+" "" /M /F config.ini /O -
call "%~dp0jrepl.bat" "^LoadRegistryManager=[01].*\r\n" "" /X /F config.ini /O -
The regular expression search string ^\[RegistryService\][^[]+ searches case-sensitive for [RegistryService] at beginning of a line and matches everything after this string up to next opening square bracket [ or end of file.
Note: This search string as is can't be used if one of the entries in section [RegistryService] contains by chance an opening square bracket.
The regular expression search string ^LoadRegistryManager=[01].*\r\n searches case-sensitive for a line starting with LoadRegistryManager= followed by digit 0 or 1, 0 or more characters except newline characters and carriage return and line-feed.
The replace string is for both replaces an empty string to delete everything matched by the search expression.
The first replace requires Multi-line mode enabled with /M. The second replace requires eXtended ASCII and escape sequences enabled with /X.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
jrepl.bat /?

Escape characters of a file path argument for a batch file

I was making a batch file to take dragged-and-dropped folders for program input. Everything was working fine until I passed a folder, which for the sake of this post, called foo&bar.
Checking what %1 contained inside the batch file looked like C:\path\to\foo or C:\path\to\foo\foo. If the file path were in quotes it would work, so the only working code that slightly takes this into effect is :
set arg1=%1
cd %arg1%*
set arg1="%CD%"
Which changes directory to the passed argument using wildcards. However this only works once for if there is another folder with un-escaped characters inside the parent folder, passing the child folder would result in the parent folders' value.
I tried the answer of this post, which suggests to output the argument using a remark and redirection statement during an #echo on sequence. However no progress occurred in rectifying the problem. Any suggestions?
To recap, I am looking for ways to pass folders with un-escaped characters as arguments to a batch file. The implementation should preferably be in a batch file, but answers using VBScript are welcome. However the starting program must be in batch as this is the only program of the 3 that accepts files as arguments.
To test this, create a batch file with following code:
#echo off
set "arg1=%~1"
echo "the passed path was %arg1%"
pause
Then create folders called foobar and foo&bar. Drag them onto the batch file to see their output. foo&bar will only return C:\path\to\foo.
OK, so the problem is that Explorer is passing this as the command line to cmd.exe:
C:\Windows\system32\cmd.exe /c ""C:\path\test.bat" C:\path\foo&bar"
The outermost quotes get stripped, and the command becomes
"C:\working\so46635563\test.bat" C:\path\foo&bar
which cmd.exe interprets similarly to
("C:\working\so46635563\test.bat" C:\path\foo) & bar
i.e., bar is considered to be a separate command, to be run after the batch file.
The best solution would be to drag-and-drop not directly onto the batch file but onto, say, a vbscript or a Powershell script or a plain old executable. That script could then run the batch file, either quoting the argument appropriately or putting the directory path into an environment variable rather than on the command line.
Alternatively, you can retrieve the original command string from %CMDCMDLINE% like this:
setlocal EnableDelayedExpansion
set "dirname=!CMDCMDLINE!"
set "dirname=%dirname:&=?%"
set "dirname=%dirname:" =*%"
set "dirname=%dirname:"=*%"
set "dirname=%dirname: =/%"
for /F "tokens=3 delims=*" %%i in ("%dirname%") do set dirname=%%i
set "dirname=%dirname:/= %"
set "dirname=%dirname:?=&%"
set dirname
pause
exit
Note the exit at the end; that is necessary so that cmd.exe doesn't try to run bar when it reaches the end of the script. Otherwise, if the part of the directory name after the & happens to be a valid command, it could cause trouble.
NB: I'm not sure how robust this script is.
I've tested it with the most obvious combinations, but YMMV. [It might be more sensible to use delayed expansion exclusively, I'm not sure. It doesn't seem to be necessary except in the first set command. Jeb's answer here might be a better choice if you're going this route.]
For the curious, the script works like this:
Load the original command line into dirname [necessary for the reason pointed out by jeb]
Replace all the & characters with ?
Replace all the quote marks with *
If a quote mark is followed by a space, suppress the space.
NB: it is necessary to suppress the space to deal with both the case where the path contains a space (in which case Explorer adds quote marks around it) and the case where it doesn't.
Replace all remaining spaces with /
NB: ? * and / are illegal in file names, so these replacements are safe.
At this point the string looks like this:
C:\Windows\system32\cmd.exe//c/**C:\path\test.bat**C:\path\foo?bar**
So we just need to pull out the third asterisk-delimited element, turn any forward slashes back into spaces and any question marks back into ampersands, and we're done. Phew!

How can I open a folder in explorer.exe with a comma in the folder name?

I have made a shortcut for opening folders based on job numbers for work. It looks through the job directory for the job number and then opens that folder. Unfortunately, this fails when the folder name has a comma "," in it:
IF %JOBNUM%==!JOBTEST! %SystemRoot%\explorer.exe %%G
Where, for example:
%%G = X:\A12300-12399\A123456 - Job with, comma
Instead of opening the job folder, it just opens My Documents (which, I assume, is the default location for Explorer.
Is there a way to let it know that the comma is part of the folder name and not some sort of delimiter?
Try adding the path inside quotes like "path"
Batch files are essentially shell commands executed as a batch. Commands are delimited by space, "," , "=" etc. As shown Here
When you use a pathname with a delimiter, windows takes the first string to be the actual value and discards the rest. Using quotes is explicitly instructing the shell to treat everything inside the quotes as a single unit. That goes the same for %%G.

search and replace file names - bug fix

I have a script that changes particular string within files names (the file stores in "my_folder"):
Set objFso = CreateObject("Scripting.FileSystemObject")
Set Folder = objFSO.GetFolder("g:\my folder")
For Each File In Folder.Files
sNewFile = File.Name
sNewFile = Replace(sNewFile,"._epf","_v0_1._epf")
if (sNewFile<>File.Name) then
File.Move(File.ParentFolder+"\"+sNewFile)
end if
Next
the scrpit works fine if there are no folders under "g:\my folder", otherewise, if there are folders in "my folder" and the name of one (or more) of those folders are similiar to some file name, the scrip cause unwanted results like multiplying the replace string.
for example if "my folder" contain:
hello (folder)
hello_.epf (file)
then the script will eventually change the file name to:
hello_v0_1_v0_1._epf (unwanted result)
and i want the result to be:
hello_v0_1._epf
I'll appreciate quick help in this manner.
thanks.
I haven't bothered to try to figure out where your VBScript is going wrong. But you tagged your question with batch-file, batch, and batch-rename.
Here is a simple one-liner that can be run from the command prompt that will do what you want. It doesn't even need a batch script.
for %F in ("g:\my folder\*._epf") do #ren "%F" "%~nF_v0_1%~xF"
If you want to run the command within a batch script, then you need to double all percents.
#echo off
for %%F in ("g:\my folder\*._epf") do ren "%%F" "%%~nF_v0_1%%~xF"
EDIT
The above will append a new version suffix to each file name, before the extension.
If you want to replace an existing version number, then the solution is even easier. I'm assuming that your version always starts with _v, and v will never occur in the file extension.
ren "g:\my folder\*_v0_1._epf" "*v0_2.*"
The above command renames all files that end with _v0_1._epf. It preserves all characters up through the last occurance of v in the name, then adds the new version number, and finally appends the original extension.
See How does the Windows RENAME command interpret wildcards? for rules on how REN uses wildcards.

Resources