Batch file rename based on data in file

June 4, 2009 at 13:27:42
Specs: Windows XP
What I need seems so simple yet I haven't been able to figure it out or find information on someone who wanted to do the same thing and came up with a solution:

I need a batch file that when run, goes through each txt file in its directory and pulled text that is in a certain position within the file and renames the file with the original name of the file plus the data that is pulled from within the file. So it would work like this:

Say I have the following files in the folder:


The batch file, when run, would pull the string comprised of a specific location in the file (let's say Line 6 Column 35 to the end of that line, leaving out trailing spaces if that's not too much extra trickery) and rename that file as such:

123A - JOHN SMITH.txt

So that the files are now named as shown above because the names were in the txt files on Line 6 starting at Column 35.

Then once it has renamed every txt file in the directory, the batch file terminates.

Seems simple right? But for some reason, I haven't been able to find out about how to do this...

See More: Batch file rename based on data in file

Report •

June 4, 2009 at 14:27:08
:: RENDATA.BAT Usage: rendata Line Colum Folder
@echo off & setlocal EnableDelayedExpansion
pushd %3
for %%i in (*.txt) do (
  type "%%i" | find /N /V "" | find "[%1]" > %~n0.tmp
  for /F "tokens=1* delims=[]" %%j in (%~n0.tmp) do (
    set line=%%k
    set line=!line:~%2!
    set norm=
    for %%z in (!line!) do set norm=!norm! %%z
  del %~n0.tmp
  ren "%%i" "%%~ni -!norm!.new"
ren *.new *.txt
:: End:Of_Batch

NOTES: Line No must take into account blank lines and must start from 1; Column No must start from 0.
If the folder's name contains blanks it must be embraced by double quotes ("). E.G.

rendata 6 34 "\Documents and Settings"

Last but not least: the above script is all than a simple batch.

Report •

June 4, 2009 at 18:25:53
here's a Python solution, if you have python on windows:
import os,glob,sys
linenum = sys.argv[1]
colnum = sys.argv[2]
for files in glob.glob("*.txt"):
    for n,line in enumerate(open(files)):        
        if n == int(linenum):
                to_get = ' '.join(line[int(colnum)-1:])
            except Exception,e:
                print e
    if to_get:
        newfilename = files[:-4]+"_"+to_get+".txt" 
            os.rename( files, newfilename )
        except Exception,e:
            print e
            print "File %s renamed to %s" %(files, newfilename)

usage: python line col <directory where files are>
c:\test> python 1 2 c:\test

Report •

June 4, 2009 at 18:30:07
>> type "%%i" | find /N /V "" | find "[%1]" > %~n0.tmp
find command finds strings in a file...2 ways
1) find /N /V "" %%i | find .... (no need type)
2) for .... in (type %%i) do
check for line and column using cmd.exe internal string processing...(ie don't use find 2 times)

this will speed up your code a little...

Report •

Related Solutions

June 5, 2009 at 03:36:52

I agree with your first note, but I don't understand the

for ... in (type %%i) do

First of all that should be coded as

for... in ('type %%i') do

then the compound statement ignores the blank lines so generating ambiguities. I prefer to number lines by Find (that doesn't ignore blank lines) than counting by myself.

I saw this time Phyton is not so terse as usual.

Report •

June 5, 2009 at 03:48:51
>>for... in ('type %%i') do
yeah... i did not put the single quote as i am merely illustrating an idea. (and i am expecting you to understand as you are the batch expert :))

>>I saw this time Phyton is not so terse as usual.
don't understand. you mean its not concise as usual? I added exception checking , one for checking if the rename is successful or not and the other check is for row and column number input by user does not exists.

Report •

June 5, 2009 at 06:33:25
Here thanks to ghostdog's hints the improved and faster version of my original script. Now the Line and Column parameters have a new format amd start from 1, e.g.

rendata L:6 C:12 "C:\Documents and Settings"

:: RENDATA.BAT Usage: rendata L:Line C:Column Folder
@echo off & setlocal EnableDelayedExpansion

set LNo=%1
set LNo=%LNo:~2%
set CNo=%2
set CNo=%CNo:~2%
set /A CNo-=1

if not exist "%~f3" (echo.  Folder "%~f3" not found & goto :EOF)
pushd "%~f3"
echo.  Processing text files in Folder "%~f3", please wait...

for %%i in (*.txt) do (
  call :SCAN %%i
  ren "%%i" "%%~ni -!norm!.new"
ren *.new *.txt
goto :EOF

  set norm=
  for /F "tokens=1* delims=[]" %%j in ('find /N /V "" "%*"') do (
    if "%%j"=="%LNo%" (
      set line=%%k
      set line=!line:~%CNo%!
      for %%z in (!line!) do set norm=!norm! %%z
      goto :EOF
goto :EOF
:: End:Of_Batch

Report •

June 5, 2009 at 06:59:12

I've only been able to find one problem with the code that you posted in your first posting: When the last token in the string that it is using has numbers in it, or is made of all numbers, the part of the batch that does the 'set norm=' part returns the error:

"A duplicate file name exists, or the file cannot be found."

Fortunately in this particular case of how I'm using the rendata.bat, the line I'm isolating to rename the file with doesn't have numbers in it. But it forseeably could, at which point the batch file wouldn't function fully.

Is there a way to tweak this so that it doesn't matter what is in the last token?

NOTE: My diagnosis of this bug is based on multiple runs with the same file using different lines, some that have numbers in the last token on the line and some that don't. So I think the conditions that make the error occur are accurate but it is possible that something else might be causing it.

Report •

June 5, 2009 at 12:52:14

please, report the string you found that causes the problem as I can't reproduce the error by strings with all numeric tokens. Anyway use the most recent version of the script as it fixes minor bugs too.

Report •

June 5, 2009 at 13:05:32
See I don't know if it has something to do with the number or if there is the odd tab character on a line that this throwing it off. But say we run it like this "rendata L:8 C:0 "whereever" "
and on that line in the file it shows this:

Joe Blow 123 Fake St. 55423

By turning echo on, I can see where it screws up and it's always on the last token on the line or in the above case on the '55432' part, and it returns the error mentioned before, doesn't rename that file and moves on to the next one.

NOTE: Apparently I can't format it in this post how it would show up in the file, but the address part would be far to the right with a lot of space between it and the name.

Report •

June 5, 2009 at 13:43:28
Hmmm... using rthe most recent version you MUST start LNo and CNo from 1, so

rendata L:8 C:1 "WhereEver"

Setting C:0 causes to ignore all tokens if there are trailing spaces or to catch just the last CHAR of the string.

Does what you posted cause the reported error while running the batch with C:1?

Report •

June 5, 2009 at 14:12:33
Anyway to add a bit of control on LNo and CNo replace in the most recent version

  ren "%%i" "%%~ni -!norm!.new"


  if defined norm (
    ren "%%i" "%%~ni -!norm!.new"
  ) else (
    echo.  "%%i" not renamed

Report •

June 8, 2009 at 05:33:49
I don't think the column reference is the cause of this problem, because it was happening when C:45 too. I just used that as an example.

Report •

Ask Question