3

I have a need of a code used in a batch file that renames bankfiles created from SAP (I am a SAP-man), stored in a location on the server.

Problem: All bank-files get a name from a sequence table in SAP (date + number). Before I send them to the bank they have to have a certain name structure.

I have a code and this has worked fine up to now. The problem now is that i send a "batch" (several) of files from SAP and they are named randomly.
In the first line of each file there is a unique batch ID, that is a bank sequence number and the files has to be named in this order. I have done a lot of VBA programming, but i am not to strong in this subject.

Needed solution: What i need is that for each file it should read the first line of the file and fetch position 71 and 4 positions forward, save this in a variable and add it to the end of the file name.

Example: If the original file name from SAP is 20160301-001.txt I want to rename it to "P.00934681758.005.TBII.00000xxxx.txt" (where "xxxx" is the position 71 to 74 in the first line of the file.

It looks through a lot of bank directories today, but below you can find todays code (that work, except that in this code it renumbers "a", starting with no 1 - never more than 9 files) and i want to replace it with these 4 digits from the file:

Todays name: P.00934681758.005.TBII.00000!a!.dat ("a" beeing a variable)

New name: P.00934681758.005.TBII.00xxxx.dat ("xxxx" the digits from the file)

Todays code (part of it - showing 2 "scanned" directories):

    @echo off & setlocal EnableDelayedExpansion 

REM Start by renaming all files in each folder to the namerule of the bank

cd PL270\UT01

set a=1

for /f "delims=" %%i in ('dir /b *') do (
    if not "%%~nxi"=="%~nx0" (
        ren "%%i" "P.00934681758.002.TBII.00000!a!".dat 
        set /a a+=1
 )
) 

cd..
cd..\PL570\UT01

set a=1

for /f "delims=" %%i in ('dir /b *') do (
    if not "%%~nxi"=="%~nx0" (
        ren "%%i" "P.00934681758.005.TBII.00000!a!".dat 
        set /a a+=1
 )
) 

The code is run in a *.bat-file today, scheduled every 5th minute on the server.

All help will be VERY much appreciated:-)

B.r. Solve

npocmaka
  • 55,367
  • 18
  • 148
  • 187
Solve
  • 31
  • 2

2 Answers2

0

As I understand the question you need to replace hardcoded a with a code readed from the file you'are renaming:

for /f "delims=" %%i in ('dir /b *') do (
    set /p fline=<"%%i"
    set code=!fline:~70,4!
    echo !code!
    if not "%%~nxi"=="%~nx0" (
        ren "%%i" "P.00934681758.002.TBII.00000!code!".dat 
        set /a a+=1
 )
)

(once I've worked for SAP - most boring I ever had...)

npocmaka
  • 55,367
  • 18
  • 148
  • 187
  • Thank you very much npocmaka:-) This worked beutifully. Simple and funtional. – Solve Mar 18 '16 at 07:14
  • By the way, I am also a financial guy - that might explain why i like working with SAP (i know some consider it to be boring:). I am having my own company together with my daughter and we have been overbooked for 10 years - not many can say that:-) – Solve Mar 18 '16 at 07:17
0

The following script walks through a given directory tree and searches for matching files. A file is considered matching if its name begins with today's date in the format YYYYMMDD, followed by a -, followed by a number, followed by extension.txt. For each file found, the demanded characters are extracted from the first line, then they are appended to the prefix P.00934681758.005.TBII.00, and the extension .dat is appended.

The behaviour of the batch file can be controlled by the constants defined at the beginning. To learn how it works and what happens, consult the rem comments throughout the whole file.

Here is the code:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Definition of constants:
set "LOCATION=%~dp0" & rem Working directory; `%~dp0` is container, `.` is current;
set "RECURSIVE=#" & rem Flag to walk through working directory recursively, if defined;
set "SEPARATOR=-" & rem Separator character of original file name (one character!);
set "PATTERN=????????%SEPARATOR%*.txt" & rem Search pattern for `dir`;
rem Filter for `findstr /R` to match only correct file names (`.*` deactivates it):
set "REGEX=[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%SEPARATOR%[0-9][0-9]*\.txt";
rem Filter for date prefix in file names (fixed date like `YYYYMMDD`, all files if empty):
set "TODAY=%DATE:~,4%%DATE:~5,2%%DATE:~8,2%" & rem Expected `%DATE%` format: `YYYY/MM/DD`;
set "NEWNAME=P.00934681758.005.TBII.00" & rem Beginning of new file name;
set "NEWEXT=.dat" & rem New file extension;
set "NUMLINE=0" & rem Zero-based line number where to extract characters from;
set "POSITION=70,4" & rem Zero-based start position, number of characters (length);
set "FORCE=#" & rem Flag to force extracted characters not to be empty, if defined;

rem Change to working directory:
pushd "%LOCATION%" || (
    >&2 echo Cannot find "%LOCATION%". & exit /B 1
)
rem Initialise some variables:
set /A NUMLINE+=0
if %NUMLINE% LEQ 0 (set "NUMSKIP=") else (set "NUMSKIP=skip^=%NUMLINE%^ ")
if defined RECURSIVE (set "RECURSIVE=/S ")
rem Walk through directory (tree) and search for matching file names (sorted by name):
for /F "eol=| delims=" %%F in ('
    dir /B %RECURSIVE%/A:-D /O:-N-D "%PATTERN%" ^| ^
        findstr /R /C:"^%REGEX%$" /C:"\\%REGEX%$"
') do (
    rem Split file name by given separator:
    for /F "eol=| tokens=1,* delims=%SEPARATOR%" %%I in ("%%~nxF") do (
        set "PREFIX=%%I"
        set "SUFFIX=%%J"
        setlocal EnableDelayedExpansion
        rem Check whether first part of file name matches today's date:
        if "%TODAY%"=="" (set "TODAY=!PREFIX!")
        if "!PREFIX!"=="!TODAY!" (
            set "OLDNAME=!PREFIX!%SEPARATOR%!SUFFIX!"
            rem Extract characters from predefined position from file (sub-routine):
            call :EXTRACT PORTION "!OLDNAME!"
            if defined FORCE (
                rem Check extracted character string if empty optionally:
                if not defined PORTION (
                    >&2 echo Nothing at position ^(%POSITION%^). & popd & exit /B 1
                )
            )
            rem Build new file name using extracted character string:
            set "BUILTNAME=%NEWNAME%!PORTION!%NEWEXT%"
            rem Check whether a file with the new name already exists:
            if not exist "!BUILTNAME!" (
                rem Actually rename file here (as soon as `ECHO` is removed!):
                ECHO ren "!OLDNAME!" "!BUILTNAME!"
            ) else (
                >&2 echo "!BUILTNAME!" already exists. & popd & exit /B 1
            )
        ) else (
            endlocal
            rem First part of file name does not match today's date, so leave loop:
            goto :CONTINUE
        )
        endlocal
    )
)
:CONTINUE
popd

endlocal
exit /B

:EXTRACT PORTION "FileSpec"
rem Sub-routine to extract characters from a file at a given position;
set "PART="
setlocal DisableDelayedExpansion
rem Read specified line from given file:
for /F usebackq^ %NUMSKIP%delims^=^ eol^= %%L in ("%~2") do (
    set "LINE=%%L"
    if defined LINE (
        setlocal EnableDelayedExpansion
        rem Extract specified sub-string of read line by position and length:
        set "PART=!LINE:~%POSITION%!"
        if  defined PART (
            for /F delims^=^ eol^= %%S in ("!PART!") do (
                endlocal
                set "PART=%%S"
            )
        ) else (
            endlocal
        )
    )
    rem Do not read any more lines from the file, leave loop:
    goto :QUIT
)
:QUIT
rem Return extracted character string:
endlocal & set "%~1=%PART%"
exit /B

The script does no renaming as long as you do not remove the upper-case ECHO in front of the ren command.

aschipfl
  • 33,626
  • 12
  • 54
  • 99