search and replace file names - bug fix - batch-file

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.

Related

Run an LibreOffice Command-Line Script through a loop

I have been able to successfully run the below code on an individual file, but I would like to find a way to have it run so that it loops through all the files shown in a directory. I believe that loops are possible within CMD.exe, but I am not having any success. Any help would be greatly appreciated.
"C:\Program Files (x86)\LibreOffice 5\program\scalc.exe" --convert-to DBF --infilter="csv:44,34,76,1,1/2/2/2/3/2/4/2/5/2/6/2/7/2/8/2/9/2/10/2/11/2/12/2/13/2/14/2/15/2/16/2/17/2/18/2/19/2/20/2/21/2/22/2/23/2/24/2/25/2/26/2/27/2/28/2/29/2/30/2/31/2/32/2/33/2/34/2/35/2/36/2/37/2/38/2/39/2/40/2/41/2/42/2/43/2/44/2/45/2/46/2/47/2/48/2/49/2/50/2/51/2/52/2/53/2/54/2/55/2/56/2/57/2/58/2/59/2/60/2/61/2/62/2/63/2/64/2/65/2/66/2/67/2/68/2/69/2/70/2/71/2/72/2/73/2/74/2/75/2/76/2/77/2/78/2/79/2/80/2/81/2/82/2/83/2/84/2/85/2/86/2/87/2/88/2/89/2/90/2/91/2/92/2/93/2/94/2/95/2/96/2/97/2/98/2/99/2/100/2/101/2/102/2/103/2/104/2/105/2/106/2/107/2/108/2/109/2/110/2/111/2/112/2/113/2/114/2/115/2/116/2/117/2/118/2/119/2/120/2/121/2/122/2/123/2/124/2/125/2/126/2/127/2/128/2/129/2/130/2/131/2/132/2/133/2/134/2/135/2/136/2,0,false,false" C:\Users\jdavidson\Desktop\DBFCONVERT\57826001_JQSAMPLE.csv --outdir C:\Users\jdavidson\desktop\complete
If you have any ideas for how I might be able to achieve this it be a huge help. I am working to build this as part of a larger workflow and make it repeatable.
UPDATE
I was able to iterate(Loop) through all of the files in my directory by creating a batch file and placing it within the directory that I am going to be using for converting moving forward
for /r %%i in (*.csv) do "C:\Program Files (x86)\LibreOffice 5\program\scalc.exe" --convert-to DBF --infilter="csv:44,34,76,1,1/2/2/2/3/2/4/2/5/2/6/2/7/2/8/2/9/2/10/2/11/2/12/2/13/2/14/2/15/2/16/2/17/2/18/2/19/2/20/2/21/2/22/2/23/2/24/2/25/2/26/2/27/2/28/2/29/2/30/2/31/2/32/2/33/2/34/2/35/2/36/2/37/2/38/2/39/2/40/2/41/2/42/2/43/2/44/2/45/2/46/2/47/2/48/2/49/2/50/2/51/2/52/2/53/2/54/2/55/2/56/2/57/2/58/2/59/2/60/2/61/2/62/2/63/2/64/2/65/2/66/2/67/2/68/2/69/2/70/2/71/2/72/2/73/2/74/2/75/2/76/2/77/2/78/2/79/2/80/2/81/2/82/2/83/2/84/2/85/2/86/2/87/2/88/2/89/2/90/2/91/2/92/2/93/2/94/2/95/2/96/2/97/2/98/2/99/2/100/2/101/2/102/2/103/2/104/2/105/2/106/2/107/2/108/2/109/2/110/2/111/2/112/2/113/2/114/2/115/2/116/2/117/2/118/2/119/2/120/2/121/2/122/2/123/2/124/2/125/2/126/2/127/2/128/2/129/2/130/2/131/2/132/2/133/2/134/2/135/2/136/2,0,false,false" C:\Users\jdavidson\Desktop\DBFCONVERT\57826001_JQSAMPLE.csv --outdir C:\Users\jdavidson\desktop\complete %%i
Note that I used a for Loop to achieve what I wanted.
for /r %%i in ('list directory if command not being run in specific directory already; you can also but * for all files in directory or *.ext for the extension of only certain files) do 'add in command %%i
Option 1: You can actually convert multiple documents with just one execution of Open/Libre Office.. without a loop. Just use a wildcard, eg:
"C:\Program Files (x86)\LibreOffice 5\program\scalc.exe" --convert-to DBF mydir\*.csv
Option 2: I assume that Windows has a limit on the number of files you can pass in that way.. not sure what that limit is.. but if you exceed that limit, you can use this python program I wrote to do this just a few days ago.. as part of a project I am still working on. In my case I am converting .doc to .odt, and obviously my directories aren't the same as yours. But it would be quite easy for you to adjust this to your needs... One thing I wanted to do with mine is to check for the existence of the converted file and skip it if it exists.. so that if a few new files are added it can be run again to convert them without redoing them all...
The docpath should be set to the location of your files, and soffice to the pathname of your Calc exe.. and if you leave things the way I have them, that's where the program puts the converted files too.. and checks for their existence. Also, I walk the path looking for input files.. so if for whatever reason you have your files in different subdirectories, it will find them and put the conversion in the same directory.
import os, sys, re, subprocess
docpath = 'doc'
soffice = 'C:\Program Files\LibreOffice 5\program\soffice.exe'
convert = '"%s" --headless --convert-to odt --outdir "%s" "%s"'
def plog(fmt = '', *args):
sys.stdout.write(fmt % args)
sys.stdout.flush()
def log(fmt = '', *args):
plog((fmt + '\n'), *args)
def convert():
odtfiles = []
for subdir, dirs, files in os.walk(docpath):
for file in files:
if not file.endswith('.doc'):
continue
docfile = os.path.join(subdir, file)
odtfile = re.sub(r"\.doc$", ".odt", docfile)
plog("%s -> %s: " % (docfile, odtfile))
if not os.path.isfile(odtfile):
plog('Converting.. ')
subprocess.check_output(convert % (soffice, docpath, docfile), shell=True)
log('OK.')
odtfiles.append(odtfile)
return odtfiles
odtfiles = convert()
Just install Python27.. and set the convert string to have the correct settings for your conversion. Along with a few other changes that should be pretty easy.. but if you need help, ask in comments.

How to rename files, removing all characters between certain values

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.

Rename file names with folder names (maybe use Python)

I have a parent folder that contains multiple folders within it. Then, each of these nested folders contains 4 files that make up a GIS shapefile and have different extensions (i.e., ".dbf", ".prj", ".shp", and ."shx"). I am new to coding (outside of R) and do not know whether this can be automated with Python or if I need to run a shell script (I'm working on a windows). I have very rudimentary coding schools so documentation would be great (and/or suggestions of "dummy" sites to read).
Here is an example of the current file structure (showing the four files I want to rename with the subfolder name):
Parent Folder: "Raptors"
Subfolder: "Falco_peregrinus"
File 1: "ra03310.dbf"
File 2: "ra03310.prj"
File 3: "ra03310.shp"
File 4: "ra03310.shx"
Here is what I would like the four files to be renamed to:
File 1: Falco_peregrinus.dbf
File 2: Falco_peregrinus.prj
File 3: Falco_peregrinus.shp
File 4: Falco_peregrinus.shx
Thanks.
For a batch file solution
#echo off
for /d %%a in ("c:\...\Raptors\*") do ren "%%~fa\*.*" "%%~na.*"
For each folder inside the parent one, rename all the files inside the folder to the name of the folder but keeping the extension
for command is used to iterate over the list of folders (/d) under the parent folder. For each of the folders, the replaceable parameter %%a will hold a reference to the subfolder and the code in the do clause is executed for each one.
The code in the do clause executes a ren command, for all the files under the subfolder (%%~fa is the folder being processed with full path), changing its name to the name of the folder (%%~na).
edited The answer is not completely correct. While the basic idea of using only one ren command to rename all the files under each folder is probably the fastest way, the way ren command handles wildcards makes this code fail if the folder name contains dots. To be sure the code will not fail, it is necessary to iterate over the files, renaming each one
for /d %%a in ("c:\...\Raptors\*") do for %%b in ("%%~fa\*") do ren "%%~fb" "%%~nxa%%~xb"
For each folder (%%a), for each file inside the folder (%%b), rename the file to the name of full folder name (%%~nxa) with the extension of the file (%%~xb)
You could use almost any programming language (probably including R) to do this. Python is a good choice here because it has such friendly syntax.
A extremely simple script that will solve your problem might look like this
import os
import os.path
'''
Given a file name, returns a pair with the name and extension (hello.txt => [hello,txt])
'''
def split_name(file_name):
return file_name.rsplit('.',1)
'''
Recursively renames files in subdirectories of base_directory so each file is named the subdirectory name plus the extension
WARNING! You will be very sad if you have multiple files with the same extension in any of those folders
def rename_file(base_directory):
#Get the folder name for base_directory (c:\users\foobar => foobar)
directory_name = os.basename(base_directory)
#List the files in base_directory
for path in os.listdir(base_directory):
old_name = base_directory + '/' + path
#If the path points to a file, rename it directory name + '.' + extension
if os.path.isfile(old_name):
new_name = base_directory + '/' + directory_name + '.' + split_name(path)[1]
if not os.path.exists(new_name):
os.rename(old_name,new_name)
else:
print("ERROR:"+new_name+" exists")
else:
#If it's a subfolder, recursively call rename files on that directory.
rename_files(old_name)
Also, I stongly suggest Learn Python The Hard Way by Zed Shaw and Dive Into Python by Mark Pilgrim
a simple windows command can solve your problem. Read HELP FOR and the try this in the Windows command line:
for /d %a in (*) do #for %b in (%a\*) do #ren %a\%b %a%~xb
let's analyze it
the first for will iterate over all (*) the directories /d and for each found, passed in %a the second for will iterate over all the files it contains (%a\*) and for each file found %b it will do rename ren it %a\%b with the name of the folder it is contained in %a keeping the same extension it had %~xb.
This can be done with batch only, I publish this script only to demonstrate how easy this is in Ruby
# enumerate all subfolders of raptors
Dir.glob("raptors/**/*/") do |folder|
# remember the prefix
pre = File.basename(folder)[/.+_/]
# enumerate all files under this folder
Dir.glob("#{folder}*.*") do |file|
File.rename(file, "#{File.dirname(file)}/#{pre}#{File.basename(file)}")
end
end
There is another answer with python code, this code changed my GIS file names based on folder name very well:
Thanks #Martin Evans.

Can't pass file path to a Batch file

I'm new to programming so apologies in advance if this is really simple.
I'm using PA File Sight to monitor a folder for open files. When a file is opened it starts a program (batch file in this case) and passes the entire file path to the variable: $Item(1)$
The batch file looks like this at the moment:
set FILE_PATH="$Item(1)$"
echo.>%FILE_PATH%_IS_OPEN
I'm trying to get the batch file to create a new file with IS_OPEN on the end of it so that users know that a file "is open"
Running the batch file creates the following in it's folder:
$Item(1)$_IS_OPEN
So it's not storing the path for some reason.
I'd suggest you try
set FILE_PATH="%~1"
echo. "%FILE_PATH%_IS_OPEN"
echo.>"%FILE_PATH%_IS_OPEN"
PAUSE
This should set FILE_PATH to the first parameter that the batch file sees - the ~ removes any enclosing quotes
The next line echoes the result to the console and may be removed if the test proves successful.
The third line encloses the proposed filename in quotes to allow the use of spaces in the filename generated.
The PAUSE holds the CMD window open until you press ENTER to allow you to see the results. It too can be removed if your results are as expected.
modified to replace the first 2 characters of the NAME portion with "AA"
set FILE_PATH="%~1"
FOR /f "delims=" %%i IN ("%file_path%") DO (SET dpi=%%~dpi&SET ni=%%~ni&SET xi=%%~xi)
SET file_path=%dpi%AA%ni:~2%%xi%
echo. "%FILE_PATH%_IS_OPEN"
echo.>"%FILE_PATH%_IS_OPEN"
PAUSE
This assumes that it's the first 2 characters that need to be replaced. It works by assuming that the literal-string in the variable file_path is a filename whic, miracle of miracles, it is. dpi is then set to the drive and path, ni to the name and xi to the extension. then the full name is reconstructed, substituting AA for the first 2 characters of the name (dpi (the path) + AA + ni:2 (the name from the second character to the end) + xi (the extension))
$Item(1)$ seems like a constant string. If $Item(1)$ is the name of an actual environment variable, your first line should be
set FILE_PATH="%$Item(1)$%"
Although that seems quite an odd name for a variable.

DOS command to move all files in subdirectories one level up without overwriting same file name, unique size

MY QUESTION:
I have the same situation as Rishi. I have a number of versions of the same song by the same artist that appear on different CD's. If I use the batch command as written, will DOS overwrite songs with the same name, even if the file size is different for each unique file?
PREVIOUS QUESTION: DOS command to move all files in subdirectories one level up
REFERENCE Rishi asked the question on Jan 15th:
"I have a folder with a lot of sub folders with one or more files in each. I am trying to write a batch file that moves all those files to C:\songs (for example).
C:>FOR /R C:\Test %i IN (*) DO MOVE %i C:\Songs
The folders Test and songs exist, but I get an error saying
%i was unexpected at this time.
What am I doing wrong?"
ANSWER WAS
"FOR /R %i IN (C:\Test*) DO MOVE "%i" C:\Songs
In a batch file, it has to be %%i. Weird quirk of batch."
Within a given folder there can only be one version of a file with a given name. When executed within a batch, the MOVE command will automatically overwrite any pre-existing file of the same name. So the answer to your question is - YES, a file with the same name will be over-written, even if it has a different file size. (Note - if you are using Windows XP then you are not using DOS)
You can prevent a batch move from overwriting an existing file by piping N to MOVE with the -y option:
echo n | move /-y "%%~i" "C:\songs\"
If you want to copy and preserve both versions into the same folder, then at least one version will have to be renamed. You will have to decide what kind of naming scheme you want to use before you can begin coming up with a solution.

Resources