I have a log file like below.
[Tue Aug 19 10:45:28 2014]Local/PLPLAN/PL/giuraja#MSAD/2172/Info(1019025)
Reading Rules From Rule Object For Database [PL]
[Tue Aug 19 10:45:28 2014]Local/PLPLAN/PL/giuraja#MSAD/2172/Info(1013157)
Received Command [Import] from user [giuraja#MSAD] using [AIF0142.rul] with data file [SQL]
.
.
.
.
.
Clear Active on User [giuraja#MSAD] Instance [1]
.
.
I want to extract the line starting with "[Tue Aug 19 10:" until the line that starts with "Clear Active on User" and output to a file using windows batch script. I tried the below code. It only outputs the last line.
#echo off & setlocal enabledelayedexpansion
set Month_Num=%date:~4,2%
if %Month_Num%==08 set Month_Name=Aug
set Day=%date:~0,3%
set Today_Date=%date:~7,2%
set Search_String=[%Day% %Month_Name% %Today_Date% 10:
for /f "tokens=1 delims=[]" %%a in ('find /n "%Search_String%"^
#(
more +%%a D:\Hyperion\ERPI_Actuals_Load\Logs\PLPLAN.LOG)>D:\Hyperion\ERPI_Actuals_Load\Logs\PLPLAN_Temp.txt
(for /f "tokens=*" %%a in (D:\Hyperion\ERPI_Actuals_Load\Logs\PLPLAN_Temp.txt) do (
set test=%%a
if "!test:~0,20!" equ "Clear Active on User" goto :eof
echo %%a
))>D:\Hyperion\ERPI_Actuals_Load\Logs\PLPLAN_Formatted.txt
Regards,
Ragav.
The Batch file below was designed to process as fast as possible a big file; however, it deletes empty lines from result:
#echo off
setlocal EnableDelayedExpansion
set "start=[Tue Aug 19 10:"
set "end=Clear Active on User"
for /F %%a in ("%start%") do set startWord=%%a
for /F %%a in ("%end%") do set endWord=%%a
set "startLine="
set "endLine="
for /F "tokens=1,2 delims=: " %%a in ('findstr /I /N /B /C:"%start%" /C:"%end%" logFile.txt') do (
if not defined startLine if "%%b" equ "%startWord%" set startLine=%%a
if not defined endLine if "%%b" equ "%endWord%" set "endLine=%%a" & goto continue0
)
:continue0
set /A skipLines=startLine-1, numLines=endLine-startLine+1
set "skip="
if %skipLines% gtr 0 set skip=skip=%skipLines%
(for /F "%skip% delims=" %%a in (logFile.txt) do (
echo %%a
set /A numLines-=1
if !numLines! equ 0 goto continue1
)) > outFile1.txt
:continue1
rem Previous outFile1.txt contain as many extra lines as empty lines removed, so we need to eliminate they
for /F "delims=:" %%a in ('findstr /I /N /B /C:"%end%" outFile1.txt') do set numLines=%%a
(for /F "delims=" %%a in (outFile1.txt) do (
echo %%a
set /A numLines-=1
if !numLines! equ 0 goto continue2
)) > outFile2.txt
:continue2
del outFile1.txt
TYPE outFile2.txt
If you want to preserve empty lines, the process would be much slower.
This should work (tested)
#echo off
set "st_line=Tue Aug 19"
set "end_line=Clear Active on User"
for /f "delims=:" %%i in ('findstr /inc:"%st_line%" logfile.txt') do (set st_line_ln=%%i)
for /f "delims=:" %%j in ('findstr /inc:"%end_line%" logfile.txt') do (set end_line_ln=%%j)
findstr /in /c:[a-z] /c:[0-9] /rc:"^$" logfile.txt >logfile_ln.txt
set /a "st_line_ln_temp=%st_line_ln-1"
for /f "skip=%st_line_ln_temp% tokens=1* delims=:" %%a in ('type logfile_ln.txt') do (
if %%a leq %end_line_ln% (echo.%%b)
)
del logfile_ln.txt
Sample output -
C:\test>type logfile.txt
Tue Aug 19 10:45:28 2014]Local/PLPLAN/PL/giuraja#MSAD/2172/Info(1019025)
Reading Rules From Rule Object For Database [PL]
[Tue Aug 19 10:45:28 2014]Local/PLPLAN/PL/giuraja#MSAD/2172/Info(1013157)
Received Command [Import] from user [giuraja#MSAD] using [AIF0142.rul] with data file [SQL]
test1
test2
test4
test546
Clear Active on User [giuraja#MSAD] Instance [1
test1212
test232
test67
dj
C:\test>draft.bat
[Tue Aug 19 10:45:28 2014]Local/PLPLAN/PL/giuraja#MSAD/2172/Info(1013157)
Received Command [Import] from user [giuraja#MSAD] using [AIF0142.rul] with data file [SQL]
test1
test2
test4
test546
Clear Active on User [giuraja#MSAD] Instance [1
C:\test>
Cheers, G
#ECHO OFF
SETLOCAL
:: If you don't want to preserve empty lines
SET "select="
(
FOR /f "delims=" %%a IN (q25390541.txt) DO (
ECHO %%a|FINDSTR /b /L /c:"[Tue Aug 19 10:" >NUL
IF NOT ERRORLEVEL 1 SET select=y
IF DEFINED select ECHO(%%a
ECHO %%a|FINDSTR /b /L /c:"Clear Active on User" >NUL
IF NOT ERRORLEVEL 1 GOTO done1
)
)>newfile.txt
:done1
:: If you want to preserve empty lines
SET "select="
(
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r ".*" q25390541.txt') DO (
IF "%%b"=="" (
IF DEFINED select ECHO(
) ELSE (
ECHO %%b|FINDSTR /b /L /c:"[Tue Aug 19 10:" >NUL
IF NOT ERRORLEVEL 1 SET select=Y
IF DEFINED select ECHO(%%b
ECHO %%b|FINDSTR /b /L /c:"Clear Active on User" >NUL
IF NOT ERRORLEVEL 1 GOTO done2
)
)
)>newfile2.txt
:done2
GOTO :EOF
I used a file named q25390541.txt containing your data for my testing.
Produces newfile.txt and newfile2.txt depending on which is preferred.
This is an inclusive (start and end line are shown) script that should do the job. You can modify it to exclude the lines:
#echo off
setlocal
set filename=text_file.txt
for /f "tokens=1 delims=:" %%a in ('findstr /n /b /c:"[Tue Aug " %filename%') do (
set /a f_line=%%a-1
)
for /f "tokens=1 delims=:" %%a in ('findstr /n /b /c:"Clear Active on User" %filename%') do (
set /a l_line=%%a
)
echo %l_line% -- %f_line%
call :tail_head2 -file=%filename% -begin=%f_line% -end=%l_line%
exit /b 0
#echo off
:tail_head2
setlocal
rem ---------------------------
rem ------ arg parsing --------
rem ---------------------------
if "%~1" equ "" goto :help
for %%H in (/h -h /help -help) do (
if /I "%~1" equ "%%H" goto :help
)
setlocal enableDelayedExpansion
set "prev="
for %%A in (%*) do (
if /I "!prev!" equ "-file" set file=%%~fsA
if /I "!prev!" equ "-begin" set begin=%%~A
if /I "!prev!" equ "-end" set end=%%A
set prev=%%~A
)
endlocal & (
if "%file%" neq "" (set file=%file%)
if "%begin%" neq "" (set /a begin=%begin%)
if "%end%" neq "" (set /a end=%end%)
)
rem -----------------------------
rem --- invalid cases check -----
rem -----------------------------
if "%file%" EQU "" echo file not defined && exit /b 1
if not exist "%file%" echo file not exists && exit /b 2
if not defined begin if not defined end echo neither BEGIN line nor END line are defined && exit /b 3
rem --------------------------
rem -- function selection ----
rem --------------------------
if defined begin if %begin%0 LSS 0 for /F %%C in ('find /c /v "" ^<"%file%"') do set /a lines_count=%%C
if defined end if %end%0 LSS 0 if not defined lines_count for /F %%C in ('find /c /v "" ^<"%file%"') do set lines_count=%%C
rem -- begin only
if not defined begin if defined end if %end%0 GEQ 0 goto :end_only
if not defined begin if defined end if %end%0 LSS 0 (
set /a end=%lines_count%%end%+1
goto :end_only
)
rem -- end only
if not defined end if defined begin if %begin%0 GEQ 0 goto :begin_only
if not defined end if defined begin if %begin%0 LSS 0 (
set /a begin=%lines_count%%begin%+1
goto :begin_only
)
rem -- begin and end
if %begin%0 LSS 0 if %end%0 LSS 0 (
set /a begin=%lines_count%%begin%+1
set /a end=%lines_count%%end%+1
goto :begin_end
)
if %begin%0 LSS 0 if %end%0 GEQ 0 (
set /a begin=%lines_count%%begin%+1
goto :begin_end
)
if %begin%0 GEQ 0 if %end%0 LSS 0 (
set /a end=%lines_count%%end%+1
goto :begin_end
)
if %begin%0 GEQ 0 if %end%0 GEQ 0 (
goto :begin_end
)
goto :eof
rem -------------------------
rem ------ functions --------
rem -------------------------
rem ----- single cases -----
:begin_only
setlocal DisableDelayedExpansion
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
if %%n GEQ %begin% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
)
)
)
endlocal
endlocal
goto :eof
:end_only
setlocal disableDelayedExpansion
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
IF %%n LEQ %end% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_eo
)
)
:break_eo
endlocal
endlocal
goto :eof
rem --- end and begin case -----
:begin_end
setlocal disableDelayedExpansion
if %begin% GTR %end% goto :break_be
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
IF %%n GEQ %begin% IF %%n LEQ %end% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_be
)
)
:break_be
endlocal
endlocal
goto :eof
rem ------------------
rem --- HELP ---------
rem ------------------
:help
echo(
echo %~n0 - dipsplays a lines of a file defined by -BEGIN and -END arguments passed to it
echo(
echo( USAGE:
echo(
echo %~n0 -file=file_to_process {-begin=begin_line ^| -end=end_line }
echo or
echo %~n0 -file file_to_process {-begin begin_line ^| -end end_line }
echo(
echo( if some of arguments BEGIN or END has a negative number it will start to count from the end of file
echo(
echo( http://ss64.org/viewtopic.php^?id^=1707
echo(
goto :eof
EDIT - last 100 lines:
#echo off
setlocal
set filename=text_file.txt
for /F %%C in ('find /c /v "" ^<"%filename%"') do set /a lines_count=%%C
set /a last_100_lines=lines_count-100
type %filename% | more /e +%last_100_lines%
Related
I have and batch file script shows me output of adb utility.
FOR /F "skip=1 delims=~" %%x IN ('adb devices -l') DO echo %%x
2 output lines
0123456789ABCDEF device product:java_joyplus_qb7 model:TM702B4_3G device:java_joyplus_qb7 transport_id:12
F9NPFP084096 device product:WW_P023 model:P023 device:P023_1 transport_id:11
I want parse non-space substring after "transport_id:".
For the first line i want get 12, for second 11. How can I do that?
If I understand correctly what you've asked, the following batch-file should output the information you require.
#Echo Off
For /F "Skip=1 Tokens=1*" %%G In ('adb.exe devices -l') Do (Set "DI=%%H"
SetLocal EnableDelayedExpansion
For /F %%I In ("!DI:*transport_id:=!") Do EndLocal & Echo %%I)
Pause
And, if you wanted to do that from cmd:
For /F "Skip=1Tokens=1*" %G In ('adb.exe devices -l')Do #Set "DI=%H"&For /F %I In ('Cmd /D/V/C Echo "!DI:*transport_id:=!"')Do #Echo %~I
You may easily extract all variables no matter their positions and show what you want:
#echo off
setlocal EnableDelayedExpansion
FOR /F "skip=1 delims=" %%a IN ('adb devices -l') DO (
for %%b in (%%a) do for /F "tokens=1,2 delims=:" %%x in ("%%b") do set "%%x=%%y"
echo Product=!product!
echo Transport=!transport_id!
)
For example:
Product=java_joyplus_qb7
Transport=12
Product=WW_P023
Transport=11
SETLOCAL EnableDelayedExpansion
REM …
FOR /F "skip=1 delims=~" %%x IN ('adb devices -l') DO (
set "_ID="&set "_transport_id="
call :parse "" "%%~x"
echo transport_id !_transport_id! (!_ID!^)
)
REM … remaining part of your script here …
goto :eof
:parse
if "%~2"=="" goto :eof
for /F "tokens=1,*" %%G in ("%~2") do (
if "%~1"=="" (
set "_ID=%%~G"
call :parse "%%~G" "%%~H"
) else (
for /F "tokens=1,2 delims=: " %%g in ("%~2") do (
if /I "%%~g"=="transport_id" (
set "_transport_id=%%~h"
) else (
call :parse "%%~G" "%%~H"
)
)
)
)
goto :eof
Tested using the following script with hard-coded hypothetical adb output (not having adb installed):
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
(
REM last token
set "_ID="&set "_transport_id="
call :parse "" "0123456789ABCDEF device product:java_joyplus_qb7 model:TM702B4_3G device:java_joyplus_qb7 transport_id:12"
echo transport_id !_transport_id! (!_ID!^)
REM penult token
set "_ID="&set "_transport_id="
call :parse "" "F9NPFP084096 device product:WW_P023 model:P023 transport_id:11 device:P023_1"
echo transport_id !_transport_id! (!_ID!^)
REM elsewhere token
set "_ID="&set "_transport_id="
call :parse "" "abc123def567 transport_id:10 device product:XX_P023 model:P023 device:P023_2"
echo transport_id !_transport_id! (!_ID!^)
REM nowhere token
set "_ID="&set "_transport_id="
call :parse "" "noTransportId sport_id:10 device product:XX_P023 model:P023 device:P023_2"
echo transport_id !_transport_id! (!_ID!^)
)
goto :eof
:parse
if "%~2"=="" goto :eof
for /F "tokens=1,*" %%G in ("%~2") do (
if "%~1"=="" (
set "_ID=%%~G"
call :parse "%%~G" "%%~H"
) else (
for /F "tokens=1,2 delims=: " %%g in ("%~2") do (
if /I "%%~g"=="transport_id" (
set "_transport_id=%%~h"
) else (
call :parse "%%~G" "%%~H"
)
)
)
)
goto :eof
Output: D:\bat\SO\61588773.bat
transport_id 12 (0123456789ABCDEF)
transport_id 11 (F9NPFP084096)
transport_id 10 (abc123def567)
transport_id (noTransportId)
I am trying call Run_sqlldr_process.bat from within batch file run_process.bat.
This is how the call is invoked in run_process.bat:
call %FWK_DIR%\run_sqlldr_process.bat !ldr!.ctl !log!.log !bad!.bad !data!.dat %BATCHUSER% %BATCHPWD% %ORACLE_SID%
echo %ERRORLEVEL%
echo %RC%
There is a failure inside run_sqlldr_process.bat after which run_sqlldr_process.bat exits with return code 1 as assigned to environment variable RC. But run_process.bat does not capture the error return code from run_sqlldr_process.bat. Both echo statements output 0 and run_process.bat completes successfully.
File Run_sqlldr_process.bat:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
REM ##########################################################################
REM # Program Name: run_process.bat
REM # Description:
REM # This script is a part of the batch framework. It contains the common
REM # functions for running batch jobs.
REM #
REM # Usage:
REM # run_process.bat <processname>
REM #
REM # History:
REM # Date Who Description
REM # ---------- ------------------ ----------------------------------------
REM # 01-Jun-2014 Ilavarasan Sekar Created
REM ##########################################################################
SET NLS_DATE_FORMAT=RRRR-MM-DD-HH24:MI
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN ('echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN ('echo %CDATE%') DO SET yyyy=%%B
SET todaysdate=%yyyy%%mm%%dd%
SET WORKFLOWLOGMONTH=%mm%%yyyy%
SET DATETIMESTAMP=%todaysdate%
for /f "tokens=1-3 delims=:." %%a in ("%time%") do SET timestamp=%%a%%b%%c
for /f "tokens=1-3 delims= " %%a in ("%timestamp%") do SET trimmed_timestamp=%%a%%b%%c
SET TIMESTAMP=%DATETIMESTAMP%_%trimmed_timestamp%
rem --- Initialize --------------------------------------------
rem Install error handler.
rem basename=$(basename $0)
SET dirname=D:/JDA/Batch_FWK/fwk
echo off
SET oldpwd=%~dp0
SET suffix=%date%
SET process_id=%1
SET job_id=
SET process_type=
SET preprocess_type=
SET postprocess_type=
SET job_status=CREATED
SET job_status_message=
SET log_level=INFO
SET pre=
if "%1" == "" goto show_usage
rem --- Include environment variables -------------------------
SET batchenv=%dirname%\batchenv.bat
if exist %batchenv% (
call %batchenv%
) else (
echo "Environment file missing.\n"
goto end
)
set LOG_FILE=%LOG_DIR%\%process_id%_%TIMESTAMP%.log
set TMP_FILE=%TMP_DIR%\%process_id%_%TIMESTAMP%.tmp
rem --- Start job ---------------------------------------------
call:start_job
IF "%preprocess_type%"=="SQL" (
call:log_info "SQL."
SET pre=%SQL_DIR%\%process_id%_pre
call %FWK_DIR%\run_sql_process.bat !pre!.sql
) ELSE IF "%preprocess_type%"=="CMD" (
call:log_info "CMD."
SET pre=%CMD_DIR%\%process_id%_pre
call %FWK_DIR%\run_cmd_process.bat !pre!.bat
) ELSE (
call:log_info "No postprocess_type."
)
IF %ERRORLEVEL% GTR 0 (
set job_status=FAILED
call:end_job
call:cleanup
set RC=1
goto end
)
rem --- Execute main process ----------------------------------
IF "%process_type%"=="SQL" (
call:log_info "SQL."
SET main=%SQL_DIR%\%process_id%
call %FWK_DIR%\run_sql_process.bat !main!.sql
) ELSE IF "%process_type%"=="CMD" (
call:log_info "CMD."
SET main=%CMD_DIR%\%process_id%
call %FWK_DIR%\run_cmd_process.bat !main!.bat
) ELSE IF "%process_type%"=="SRE" (
call:log_info "SRE."
SET main=%XML_DIR%\%process_id%
call %FWK_DIR%\run_sre_process.bat !main!.xml
) ELSE IF "%process_type%"=="PERL" (
call:log_info "PERL."
SET main=%PRL_DIR%\%process_id%
call %FWK_DIR%\run_perl_process.bat !main!.pl
) ELSE IF "%process_type%"=="SQLLDR" (
call:log_info "SQLLDR."
SET ldr=%CTL_DIR%\%process_id%
SET log=%LOG_DIR%\%process_id%_%TIMESTAMP%
SET bad=%BAD_DIR%\%process_id%_%TIMESTAMP%
SET data=%IN_DIR%\%process_id%
call %FWK_DIR%\run_sqlldr_process.bat !ldr!.ctl !log!.log !bad!.bad !data!.dat %BATCHUSER% %BATCHPWD% %ORACLE_SID%
echo Return Code ERRORLEVEL inside run_process is %ERRORLEVEL%
echo Return Code inside run_process.bat is %RC%
IF %RC% GTR 0 (
ECHO INSIDE FAILED BLOCK
set job_status=FAILED
set RC=1
call:end_job
call:cleanup
goto end
)
) ELSE (
call:log_info "Unsupported process type %process_type%."
set job_status=FAILED
set RC=1
call:end_job
call:cleanup
goto end
)
IF %ERRORLEVEL% GTR 0 (
set job_status=FAILED
set RC=1
call:end_job
call:cleanup
goto end
)
IF "%postprocess_type%"=="SQL" (
call:log_info "SQL."
SET post=%SQL_DIR%\%process_id%_post
call %FWK_DIR%\run_sql_process.bat !post!.sql
) ELSE IF "%postprocess_type%"=="CMD" (
call:log_info "CMD."
SET post=%CMD_DIR%\%process_id%_post
call %FWK_DIR%\run_cmd_process.bat !post!.bat
) ELSE (
call:log_info "No postprocess_type."
)
IF %ERRORLEVEL% GTR 0 (
set job_status=FAILED
set RC=1
call:end_job
call:cleanup
goto end
)
rem --- End job -------------------------------------------------
call:end_job
call:cleanup
goto end
:show_usage
#echo Usage: Usage is run_process.bat ProcessName
goto end
rem --- Function definitions ----------------------------------
rem -----------------------------------------------------------
rem Function Name: start_job
rem Description :
rem Retrieve process properties and start a new job for
rem the specified process.
rem Input : process_id - Process to start.
rem Output : job_id - New job id set.
rem -----------------------------------------------------------
:start_job
call:log_info "--- Starting -----------------------------------"
call:log_info "Process : %process_id%"
call:log_info "Environment : %ENV_NAME%"
call:log_info "Batch root : %ENV_HOME%"
call:log_info "Log file : %LOG_FILE%"
call:log_info "Tmp file : %TMP_FILE%"
sqlplus -s /nolog #%dirname%/sqlFile.sql '%BATCHUSER%' '%BATCHPWD%' '%ORACLE_SID%' '%process_id%'
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_ID" %tmp_file%') do set JOB_ID=%%a
for /f "tokens=1,*" %%a in ("%JOB_ID%") do set JOB_ID=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^PROCESS_TYPE" %tmp_file%') do set PROCESS_TYPE=%%a
for /f "tokens=1,*" %%a in ("%PROCESS_TYPE%") do set PROCESS_TYPE=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^PREPROCESS_TYPE" %tmp_file%') do set PREPROCESS_TYPE=%%a
for /f "tokens=1,*" %%a in ("%PREPROCESS_TYPE%") do set PREPROCESS_TYPE=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^POSTPROCESS_TYPE" %tmp_file%') do set POSTPROCESS_TYPE=%%a
for /f "tokens=1,*" %%a in ("%POSTPROCESS_TYPE%") do set POSTPROCESS_TYPE=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^LOG_LEVEL" %tmp_file%') do set LOG_LEVEL=%%a
for /f "tokens=1,*" %%a in ("%LOG_LEVEL%") do set LOG_LEVEL=%%a
set job_status=RUNNING
del /q %TMP_FILE%
IF "%job_id%" == "" (
set job_status=FAILED
call:cleanup
set RC=1
goto end
)
call:log_info "Job id : %job_id%"
call:log_info "Process type : %process_type%"
call:log_info "Pre-process type : %preprocess_type%"
call:log_info "Post-process type: %postprocess_type%"
call:log_info "--- Running ------------------------------------"
goto:eof
rem -----------------------------------------------------------
rem Function Name: end_job
rem Description :
rem End the current job.
rem Input : job_id
rem Output : N/A
rem -----------------------------------------------------------
:end_job
call:log_info "--- Ending -------------------------------------"
sqlplus -s /nolog #%dirname%/sqlFileEnd.sql '%BATCHUSER%' '%BATCHPWD%' '%ORACLE_SID%' '%job_id%' '%job_status%'
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_STATUS|" %tmp_file%') do set JOB_STATUS=%%a
for /f "tokens=1,*" %%a in ("%JOB_STATUS%") do set JOB_STATUS=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_STATUS_MESSAGE" %tmp_file%') do set JOB_STATUS_MESSAGE=%%a
for /f "tokens=1,*" %%a in ("%JOB_STATUS_MESSAGE%") do set JOB_STATUS_MESSAGE=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_VOLUME" %tmp_file%') do set JOB_VOLUME=%%a
for /f "tokens=1,*" %%a in ("%JOB_VOLUME%") do set JOB_VOLUME=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_ERROR_COUNT" %tmp_file%') do set JOB_ERROR_COUNT=%%a
for /f "tokens=1,*" %%a in ("%JOB_ERROR_COUNT%") do set JOB_ERROR_COUNT=%%a
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_WARNING_COUNT" %tmp_file%') do set JOB_WARNING_COUNT=%%a
for /f "tokens=1,*" %%a in ("%JOB_WARNING_COUNT%") do set JOB_WARNING_COUNT=%%a
del /q %TMP_FILE%
call:log_info "Job status : %job_status%"
call:log_info "Job status msg : %job_status_message%"
rem call:log_info "Volume : %job_volume%"
call:log_info "Error count : %job_error_count%"
call:log_info "Warning count : %job_warning_count%"
goto:eof
rem -----------------------------------------------------------
rem Function Name: fatal
rem Description :
rem Error handler called called by trap on error etc.
rem Handle clean up and exit with error.
rem Input : Return code from failed command in ?.
rem Output : N/A
rem -----------------------------------------------------------
rem -----------------------------------------------------------
rem Function Name: clear
rem Description :
rem Handle clean up.
rem Input : N/A
rem Output : N/A
rem -----------------------------------------------------------
:cleanup
if not '%job_status%' == 'COMPLETED' (
call:log_info "--------- Ended with failure -------------------------"
) else (
call:log_info "----------------------- End --------------------------"
)
goto:eof
rem -----------------------------------------------------------
rem Function Name: log_info
rem Description :
rem Write information to log file and stdout.
rem Input : 1 - Message to log.
rem Output : N/A
rem -----------------------------------------------------------
:log_info
set stamp=%TIMESTAMP%
rem echo [INFO.][%stamp%] %1
rem echo.
rem echo %LOG_FILE%
echo [INFO.][%stamp%] %1 >> %LOG_FILE%
echo. >> %LOG_FILE%
goto:eof
:end
exit /b %RC%
endlocal
Why does error handling after calling a batch file not work as expected in my batch file?
I have re-written your CMD script to be MUCh tighter, and I Put in a variable to set the FWK variable, and there are other variables that are being set that are not being used I removed many of them from here, and there are additional script variables that are not being set by you from anywhere That I ca find, perhaps they are coming from the other .bat file?>
Lets go through this in chat in more detail as there are several unknowns and I obviously can;t test this myself as it depends so heavily on the custom scripts you have.
:: ##########################################################################
:: # Program Name: run_process.bat
:: # Description:
:: # This script is a part of the batch framework. It contains the common
:: # functions for running batch jobs.
:: #
:: # Usage:
:: # run_process.bat <processname>
:: #
:: # History:
:: # Date Who Description
:: # ---------- ------------------ ----------------------------------------
:: # 01-Jun-2014 Ilavarasan Sekar Created
:: ##########################################################################
::
#(
echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "_eLvl=0"
IF /I "%1" EQU "" (
CALL :Show_Usage
Exit /B 1
)
REM ENTER YOUR DIRECTORIES
SET "dirname=D:\JDA\Batch_FWK\fwk"
SET "FWK_DIR=C:\SOME\DIRECTORY"
REM If Batch Environment Bat File is missing Quit! Otherwise load it and continue
SET "batchenv=!dirname!\batchenv.bat"
IF NOT EXIST "!batchenv!" (
ECHO Environment file !batchenv!" is missing.
Exit /B 1
)
CALL "!batchenv!"
SET "_Write-Info=call :log_info "
)
CALL :Main
(
ENDLOCAL
EXIT /B %_eLvl%
)
:Main
CALL :Initialize_Variables
rem --- Start job ---------------------------------------------
call :start_job
FOR %A IN (
Step1
Step2
Step3
) DO (
IF /I !_eLvl! LEQ 0 (
ECHO. Running :%%A
CALL :%%A
) ELSE (
ECHO Error Occured! Skipping :%%A
)
)
IF !_eLvl! GTR 0 (
SET "job_status=FAILED"
)
rem --- End job -------------------------------------------------
call :end_job
GOTO :EOF
:Initialize_Variables
rem --- Initialize --------------------------------------------
REM SET "NLS_DATE_FORMAT=RRRR-MM-DD-HH24:MI"
REM --- Set up the Date Variable
FOR /F "Tokens=1-7 delims=MTWFSmtwfsouehrandit:-\/. " %%A IN ("%DATE% %TIME: =0%") DO (
FOR /F "Tokens=2-4 Skip=1 Delims=(-)" %%a IN ('ECHO.^| DATE') DO (
SET "_%%~a=%%~A"
SET "_%%~b=%%~B"
SET "_%%~c=%%~C"
SET "TIMESTAMP=!_YY!!_mm!!_dd!_%%~D%%~E%%~F"
)
)
REM Setup Logs:
SET "LOG_FILE=%LOG_DIR%\%process_id%_%TIMESTAMP%.log"
SET "TMP_FILE=%TMP_DIR%\%process_id%_%TIMESTAMP%.tmp"
rem Install error handler.
rem basename=$(basename $0)
REM Setup the Process Info and default variable States
SET "process_id=%1"
SET "job_id="
SET "process_type="
SET "preprocess_type="
SET "postprocess_type="
SET "job_status=CREATED"
SET "job_status_message="
SET "log_level=INFO"
SET "pre="
GOTO :EOF
:show_usage
#echo Usage: Usage is run_process.bat ProcessName
GOTO :EOF
:start_job
rem --- Function definitions ----------------------------------
rem -----------------------------------------------------------
rem Function Name: start_job
rem Description :
rem Retrieve process properties and start a new job for
rem the specified process.
rem Input : process_id - Process to start.
rem Output : job_id - New job id set.
rem -----------------------------------------------------------
%_Write-Info%"--- Starting -----------------------------------"
%_Write-Info%"Process : %process_id%"
%_Write-Info%"Environment : %ENV_NAME%"
%_Write-Info%"Batch root : %ENV_HOME%"
%_Write-Info%"Log file : "%LOG_FILE%""
%_Write-Info%"Tmp file : "%TMP_FILE%" "
sqlplus -s /nolog #"%dirname%/sqlFile.sql" '%BATCHUSER%' '%BATCHPWD%' '%ORACLE_SID%' '%process_id%'
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_ID" "%TMP_FILE%" ') do SET "JOB_ID=%%a"
for /f "tokens=1,*" %%a in ("%JOB_ID%") do SET "JOB_ID=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^PROCESS_TYPE" "%TMP_FILE%" ') do SET "PROCESS_TYPE=%%a"
for /f "tokens=1,*" %%a in ("%PROCESS_TYPE%") do SET "PROCESS_TYPE=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^PREPROCESS_TYPE" "%TMP_FILE%" ') do SET "PREPROCESS_TYPE=%%a"
for /f "tokens=1,*" %%a in ("%PREPROCESS_TYPE%") do SET "PREPROCESS_TYPE=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^POSTPROCESS_TYPE" "%TMP_FILE%" ') do SET "POSTPROCESS_TYPE=%%a"
for /f "tokens=1,*" %%a in ("%POSTPROCESS_TYPE%") do SET "POSTPROCESS_TYPE=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^LOG_LEVEL" "%TMP_FILE%" ') do SET "LOG_LEVEL=%%a"
for /f "tokens=1,*" %%a in ("%LOG_LEVEL%") do SET "LOG_LEVEL=%%a"
SET "job_status=RUNNING"
del /q "%TMP_FILE% ""
IF "%job_id%" == "" (
SET "job_status=FAILED"
SET "_eLvl=1"
)
%_Write-Info%"Job id : %job_id%"
%_Write-Info%"Process type : %process_type%"
%_Write-Info%"Pre-process type : %preprocess_type%"
%_Write-Info%"Post-process type: %postprocess_type%"
%_Write-Info%"--- Running ------------------------------------"
goto :eof
:Step1
(
ECHO."SQL CMD" | FIND /I /V "%preprocess_type%" (
) && (
%_Write-Info%"No Prerocess_type."
)
) || (
CALL SET "pre=!%preprocess_type%_DIR!\%process_id%_pre"
CALL "%FWK_DIR%\run_sql_process.bat" "!pre!.%preprocess_type%"
)
SET "_eLvl=%ERRORLEVEL%"
GOTO :EOF
:Step2
rem --- Execute main process ----------------------------------
SET "_Valid_Procs=SQL CMD SRE PERL SQLLDR"
SET "_SQL.Ext=SQL"
SET "_CMD.Ext=CMD"
SET "_Perl.Ext=pl"
SET "_SRE.Ext=xml"
rem Check is valid Process Type
ECHO."%_Valid_Procs%" | FIND /I /V "%process_type%" >NUL && (
%_Write-Info%"Unsupported process type %process_type%."
SET "job_status=FAILED"
SET "_eLvl=1"
GOTO :EOF
)
IF /I "%process_type%" EQU "SQLLDR" (
%_Write-Info%"SQLLDR."
SET "ldr=%CTL_DIR%\%process_id%"
SET "log=%LOG_DIR%\%process_id%_%TIMESTAMP%"
SET "bad=%BAD_DIR%\%process_id%_%TIMESTAMP%"
SET "data=%IN_DIR%\%process_id%"
CALL SET "FWK_CMD=%FWK_DIR%\run_SQLLDR_process.bat" !ldr!.ctl !log!.log !bad!.bad !data!.dat %BATCHUSER% %BATCHPWD% %ORACLE_SID%"
) ELSE (
FOR %%A IN (
%_Valid_Procs%"
) DO (
%_Write-Info%"%%A."
CALL SET "FWK_CMD="%FWK_DIR%\run_%%A_process.bat" "Main=!%%A_DIR!\%process_id%.!_%%A.ext!""
)
)
%_Write-Info% Running: %FWK_CMD%
call "%FWK_CMD%"
SET "_eLvl=%ERRORLEVEL%"
GOTO :EOF
:Step3
(
ECHO."SQL CMD" | FIND /I /V "%postprocess_type%" (
) && (
%_Write-Info%"No Prerocess_type."
)
) || (
CALL SET "pre=!%preprocess_type%_DIR!\%process_id%_post"
CALL "%FWK_DIR%\run_%preprocess_type%_process.bat" "!pre!.%preprocess_type%"
)
SET "_eLvl=%ERRORLEVEL%"
GOTO :EOF
:end_job
rem -----------------------------------------------------------
rem Function Name: end_job
rem Description :
rem End the current job.
rem Input : job_id
rem Output : N/A
rem -----------------------------------------------------------
%_Write-Info%"--- Ending -------------------------------------"
sqlplus -s /nolog #%dirname%/sqlFileEnd.sql '%BATCHUSER%' '%BATCHPWD%' '%ORACLE_SID%' '%job_id%' '%job_status%'
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_STATUS|" "%TMP_FILE%" ') do SET "JOB_STATUS=%%a"
for /f "tokens=1,*" %%a in ("%JOB_STATUS%") do SET "JOB_STATUS=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_STATUS_MESSAGE" "%TMP_FILE%" ') do SET "JOB_STATUS_MESSAGE=%%a"
for /f "tokens=1,*" %%a in ("%JOB_STATUS_MESSAGE%") do SET "JOB_STATUS_MESSAGE=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_VOLUME" "%TMP_FILE%" ') do SET "JOB_VOLUME=%%a"
for /f "tokens=1,*" %%a in ("%JOB_VOLUME%") do SET "JOB_VOLUME=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_ERROR_COUNT" "%TMP_FILE%" ') do SET "JOB_ERROR_COUNT=%%a"
for /f "tokens=1,*" %%a in ("%JOB_ERROR_COUNT%") do SET "JOB_ERROR_COUNT=%%a"
for /f "tokens=2 delims=|" %%a in ('findstr /R /I "^JOB_WARNING_COUNT" "%TMP_FILE%" ') do SET "JOB_WARNING_COUNT=%%a"
for /f "tokens=1,*" %%a in ("%JOB_WARNING_COUNT%") do SET "JOB_WARNING_COUNT=%%a"
del /q "%TMP_FILE%"
%_Write-Info%"Job status : %job_status%"
%_Write-Info%"Job status msg : %job_status_message%"
rem %_Write-Info%"Volume : %job_volume%"
%_Write-Info%"Error count : %job_error_count%"
%_Write-Info%"Warning count : %job_warning_count%"
CALL :Cleanup
goto :eof
:cleanup
rem -----------------------------------------------------------
rem Function Name: clear
rem Description :
rem Handle clean up.
rem Input : N/A
rem Output : N/A
rem -----------------------------------------------------------
if not '%job_status%' == 'COMPLETED' (
%_Write-Info%"--------- Ended with failure -------------------------"
) else (
%_Write-Info%"----------------------- End --------------------------"
)
goto :eof
:log_info
rem -----------------------------------------------------------
rem Function Name: log_info
rem Description :
rem Write information to log file and stdout.
rem Input : 1 - Message to log.
rem Output : N/A
rem -----------------------------------------------------------
SET "stamp=%TIMESTAMP%"
rem echo [INFO.][%stamp%] %1
rem echo.
rem echo "%LOG_FILE%"
echo.[INFO.][%stamp%] %*>> "%LOG_FILE%"
echo.>> "%LOG_FILE%"
goto :eof
With below code I'm struggling to print calculation for each value in a given list. Currently it prints total combined time for both users, I want to echo individual time for each user which is listed in 2nd row of this code.\
Any help will be appreciated.
#Echo off
For %%U in (a3rgcw shukla) Do (
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
Set "TotalSecs=0"
For %%F in ("*%U%*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Echo TotalDuration for %%U:%TotalDur%
)
Echo:
PopD
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
::Echo Session from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%
Goto :Eof
Current output:
TotalDuration for a3rgcw: 7:15:00
TotalDuration for shukla: 7:15:00
Desired output:
TotalDuration for a3rgcw: 5:15:00
TotalDuration for shukla: 2:00:00
Sample file named shukladfdf for 2nd user:
sdsdf system log created on ghg Thursday, 9 August 2018, 20:30:45 on India
Standard Time
dfg
drdwewed
end of session as 9 August 2018, 22:30:45 on India Standard Time
#Echo off
Setlocal
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
For %%U in (a3rgcw shukla) Do (
Set "TotalDur="
Set "TotalSecs=0"
For %%F in ("*%%U*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "FileName=%%F"
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Set "UsrName=%%U: "
Call :Print UsrName
)
Echo:
PopD
Goto :Eof
:Print
If /i "%~1" == "UsrName" (
Echo TotalDuration for %UsrName:~,10% %TotalDur%
) else If /i "%~1" == "FileName" (
Echo Session (%FileName%^) from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
)
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
Call :Print FileName
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%"
Goto :Eof
Changed %U% to %%U.
Changed Echo TotalDuration for %%U:%TotalDur% to
Call Echo TotalDuration for %%U:%%TotalDur%% which
delays expansion until time of execution, instead of
parse time.
Added missing double quote with 2nd last line to close.
Added Setlocal to top of script as perhaps a 2nd run
of the script in the same CMD session could set
predined variables with values.
Added label :Print to echo the output to avoid
use of delayed expansion.
In a batch file I get a folder with a list of subfolders with an unknown number of underscores e.g.:
a_b_10
c_d_e_2
f_17
I need to remove the last token of the names i.e.
a_b
c_d_e
f
Thanks
You could try to get the last part with an underscore and then remove this from your string, but this only works when the last part is unique.
In your sample the last part seems to be always a number in spite of the other parts.
This uses the trick to parse parts of a string by replace the delimiter by a linefeed character.
#echo off
setlocal EnableDelayedExpansion
set LF=^
for /F "delims=" %%X in ('dir /b /AD') do (
call :removeLastPart "%%~X"
)
exit /b
:removeLastPart
set "str=%~1"
for %%L in ("!LF!") DO (
for /F "delims=" %%P in ("!str:_=%%~L!") do set "last=%%P"
)
echo The last part is '!last!'
REM ** now remove the last part by replacing with nothing **
set "str=!str:_%last%=!"
echo !str!
exit /b
#echo off
set "root_dir=C:\scriptests"
setlocal enableDelayedExpansion
for /f %%d in ('dir /b /a:d *_*') do (
call :lastindexof "%%d" _ lio
set "f_name=%%~d"
echo renaming !f_name!
for %%S in (!lio!) do ren !f_name! !f_name:~0,%%S!
)
endlocal
exit /b 0
:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
#echo off
setlocal disableDelayedExpansion
set "str=%~1"
set "splitter=%~2"
set LF=^
rem ** Two empty lines are required
setlocal enableDelayedExpansion
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!str:%%R=%%L!"
)
)
for /f delims^=^" %%P in ("!var!") DO (
set "last_part=%%~P"
)
if "!last_part!" equ "" if "%~3" NEQ "" (
echo "not contained" >2
endlocal
set %~3=-1
exit
) else (
echo "not contained" >2
endlocal
echo -1
)
call :strlen0.3 str strlen
call :strlen0.3 last_part plen
call :strlen0.3 splitter slen
set /a lio=strlen-plen-slen
endlocal & set lio=%lio%
endlocal & if "%~3" NEQ "" (set %~3=%lio%) else echo %lio%
exit /b 0
:strlen0.3 StrVar [RtnVar]
setlocal EnableDelayedExpansion
set "s=#!%~1!"
set "len=0"
for %%A in (2187 729 243 81 27 9 3 1) do (
set /A mod=2*%%A
for %%Z in (!mod!) do (
if "!s:~%%Z,1!" neq "" (
set /a "len+=%%Z"
set "s=!s:~%%Z!"
) else (
if "!s:~%%A,1!" neq "" (
set /a "len+=%%A"
set "s=!s:~%%A!"
)
)
)
)
endlocal & if "%~2" neq "" (set %~2=%len%) else echo **%len%**
exit /b
This solution will create the "renfolders.bat.txt" file for you to check in notepad, and run it as a batch file if you are happy with it.
This uses a helper batch file called repl.bat - download from: https://www.dropbox.com/s/qidqwztmetbvklt/repl.bat
Place repl.bat in the same folder as the batch file or in a folder that is on the path.
dir *_* /b /s /ad |repl ".*\\(.*)_.*" "ren \q$&\q \q$1\q" xa >"renfolders.bat.txt"
I just figured out this solution:
for /f %%f in ('dir /b /AD c:\MainFolder\') do (
set var=%%f
set var=!var:_= !
set /a count=0
for %%i in (!var!) do (set /a count+=1)
set /a count2=0
for %%i in (!var!) do (
set /a count2+=1
if /I !count2! equ 1 (set var2=%%i) else if not !count2! equ !count! (set var2=!var2!_%%i)
)
echo !var2!
)
Here is a novel approach
For each folder containing at least one _ in name:
create a temporary empty file with the same name
rename the temporary file, stripping off everything after the final _
read the new name into a variable
strip off the final _ from the name
For an explanation of how the rename works, see How does the Windows RENAME command interpret wildcards?
#echo off
setlocal enableDelayedExpansion
set "loc=%temp%\removeToken"
md "%loc%"
for /d %%F in (*_*) do (
copy nul "%loc%\%%F" >nul
ren "%loc%\*" "*_"
for %%A in ("%loc%\*") do set "new=%%~nxA"
del /q "%loc%\*"
echo old=%%F
echo new=!new:~0,-1!
echo(
)
rd "%loc%"
EDITED - Wrong copy of the code posted
It separates the elements of the directory name and iterates over them discarting the last element
#echo off
setlocal enabledelayedexpansion
for /d %%a in (*_*) do (
set "old=%%~na" & set "new=" & set "previous="
for %%b in ("!old:_=" "!") do (
if not defined previous (
set "previous=%%~b"
) else if not defined new (
set "new=!previous!"
) else set "new=!new!_!previous!"
set "previous=%%~b"
)
echo ren "%%~fa" "!new!"
)
endlocal
I need to get file name with out the file extension, folder name out putted to a csv file. I am able to get file name and folder name using:
#ECHO OFF
SETLOCAL
PUSHD "%~1"
FOR /f "delims=" %%i IN ("%cd%") DO SET directory=%%~nxi
(
FOR /f "delims=" %%i IN ('dir /b /a-d /on') DO (
SETLOCAL enabledelayedexpansion
ECHO "%%i","!directory!"
endlocal
)
)>filelist.csv
How can I rewrite this so the file extension is removed and if there are subfolders it will grab the subfolder name too?
#echo off
setlocal enableextensions disabledelayedexpansion
if not "%~1"=="" (
(for /f "tokens=*" %%i in ('dir /s /b /on "%~1\*"') do (
set "file=%%~dpni"
setlocal enabledelayedexpansion
echo(!file:%~dp1=!
endlocal
)) > filelist.csv
) else (
call "%~f0" "%cd%"
)
endlocal
Not sure about the final format. Try and comment.
EDITED - to handle case exposed by Andriy M
#echo off
setLocal
pushd "%~1"
set "cur_path=%cd:~2%"
setLocal enableDelayedExpansion
FOR /f "delims=" %%i IN ('dir /b /s /a-d /on') DO (
SET "file_path=%%~dpni"
SET "file_path=!file_path:~2!"
SET "file_path=!file_path:%cur_path%=!"
ECHO "!file_path!","%%~di%cur_path%"
)
endLocal
endLocal
EDIT
with additional ~ replacing (comparatively slow - could be optimized with macros... ):
#echo off
pushd .
set "cur_path=%cd:~2%"
call :wavereplacer "%cur_path%" "-" nw_cur_path
setlocal enableDelayedExpansion
FOR /f "delims=" %%i IN ('dir /b /s /a-d /on') DO (
SET "file_path=%%~dpni"
SET "file_path=!file_path:~2!"
SET "file_path=!file_path:%cur_path%=!"
CALL :wavereplacer "!file_path!" "-" file_path
ECHO "!file_path!","%%~di%nw_cur_path%"
)
endlocal
endlocal
goto :eof
:wavereplacer String Replacer [RtnVar]
setlocal
rem the result of the operation will be stored here
set "result=#%~1#"
set "replacer=%~2"
call :strlen0.3 result wl
call :strlen0.3 replacer rl
:start
set "part1="
set "part2="
rem splitting the string on two parts
for /f "tokens=1* delims=~" %%w in ("%result%") do (
set "part1=%%w"
set "part2=%%x"
)
rem calculating the count replace strings we should use
call :strlen0.3 part1 p1l
call :strlen0.3 part2 p2l
set /a iteration_end=wl-p1l-p2l
rem creating a sequence with replaced strings
setlocal enableDelayedExpansion
set "sequence="
for /l %%i in (1,1,%iteration_end%) do (
set sequence=!sequence!%replacer%
)
endlocal & set "sequence=%sequence%"
rem adjust the string length
set /a wl=wl+iteration_end*(rl-1)
rem replacing for the current iteration
set result=%part1%%sequence%%part2%
rem if the second part is empty the task is over
if "%part2%" equ "" (
set result=%result:~1,-1%
goto :endloop
)
goto :start
:endloop
endlocal & if "%~3" neq "" (set %~3=%result%) else echo %result%
exit /b
:strlen0.3 StrVar [RtnVar]
setlocal EnableDelayedExpansion
set "s=#!%~1!"
set "len=0"
for %%A in (2187 729 243 81 27 9 3 1) do (
set /A mod=2*%%A
for %%Z in (!mod!) do (
if "!s:~%%Z,1!" neq "" (
set /a "len+=%%Z"
set "s=!s:~%%Z!"
) else (
if "!s:~%%A,1!" neq "" (
set /a "len+=%%A"
set "s=!s:~%%A!"
)
)
)
)
endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len%
exit /b