0

I am trying to create batch script that edits few java files in project due to some development environment issues. One of the files have text which needs to be commented.
So text (say abc(); ) will become commented text (//abc();).
Thus, I need to add double forward slash. I was trying to use find and replace text (FART) utility to replace text. But its creating issue with slashes. Any idea on how to proceed with this will be really helpful.

What I tried till yet:
fart.exe file.java abc(); //abc();
fart.exe -C file.java abc(); //abc();
fart.exe -C file.java "abc();" "//abc();"
fart.exe -C file.java abc(); ^/^/abc();
fart.exe -C file.java abc(); \/\/abc();
Unfortunately, none of them are working and I am out of ideas.


Taking help from link:

https://stackoverflow.com/questions/23359371/remove-slash-blackslash-using-fart

remove slash , blackslash using FART
I used
fart.exe -C file.java abc(); "\/\/abc();"
This works but also produces some warnings.

Secondly, is there restriction that only first instance can be replaced in fart. In a file, there were multiple occurrences and it printed 6 lines where occurrence was found but replaced none of them.

Thanks for helping me out.

Community
  • 1
  • 1
ashu
  • 1,197
  • 2
  • 14
  • 30
  • Am I the only one who considers this tool very poorly named...? :-) – Thorsten Dittmar Nov 09 '16 at 15:40
  • I am with you @ThorstenDittmar :-) And thats why I renamed its exe with rep.exe.. Some name it is... – ashu Nov 09 '16 at 15:43
  • Try `fart.exe -C file.java "abc();" "\/\/abc();"` with `abc();` also enclosed in double quotes because of the round brackets in string. What about using a different tool, see [How can you find and replace text in a file using the Windows command-line environment?](http://stackoverflow.com/questions/60034/) My favorite is __xchang32__ which would do this replace job with `xchang32.exe file.java "abc();" "//abc();"`. – Mofi Nov 09 '16 at 17:55
  • Thanks @Mofi I read the link. Its a part of Clay's utility. This means I will need whole package for it to work. I am not sure if that's allowed, given most of the links are blocked. I am open to shift to any new utility which is standalone and not dependent on some other installation (like .net or java/python etc or any other PL). Correct me if I am wrong – ashu Nov 09 '16 at 18:58
  • @ashu Clay's Utilities (plural) is a ZIP file containing multiple stand-alone executables. __xchang32__ is one of them. You don't need anything else from the ZIP file if you want to use only this executable. The executable has no dependencies on DLLs with the exception of Windows kernel and user DLLs on which every application depends on. It can be run from anywhere on any 32-bit Windows as well as any 64-bit Windows with x86 compatibility. – Mofi Nov 11 '16 at 09:13

2 Answers2

0

I see you are open to alternatives? This is most easily done in Powershell these days, although I can write a cmd to make it work too, it's far more laborious to do so.

If you are open to using Powershell pop the following into your Admin-Enabled Command Prompt (no need to open a PowwerShell prompt):

Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

Brief Note: I wanted to handle you re-running it on a file so I had to check so make sure you didn't keep adding braces to your text.

Ben Personick
  • 3,074
  • 1
  • 22
  • 29
  • Powershell was my choice. But unfortunately, it was blocked and we dont have admin rights. So I started batch. I will try on an open system and if it works there, will see if I can get access to powershell. Thanks anyways :) – ashu Nov 10 '16 at 07:01
  • I understand how that is, can you at least write a temp file? I like to do as much in memory as possible even in CMD however when it comes to reading file contents there is always a fair chance you will hit the limit of variable (aprox 4096 Bytes) expressions or loop variables (Approx 8192 Bytes) and making sure to use .cmd to get 64bit and utilizing recursion will really only push that by a couple of orders of magnitude at most. It's far less error prone and far simpler code to write a batch which would write the whole file to a temp file and move it and replace the original. – Ben Personick Nov 11 '16 at 06:39
  • here is this going to be your best bet if you can use a temp file anfd be quick and dirty: – Ben Personick Nov 11 '16 at 06:40
  • Tried powershell. Unfortunately, it has been blocked organization wide. Thanks for your help anyway. It will come handy in some other situation :) – ashu Nov 15 '16 at 07:13
0

I understand how that is and I've spent a long night and morning working on remembering how I did this last time and writing the script below for you.

I have worked mostly within that sphere for the last 10 years or so as I got sick the inconsistencies in VBScript, and needed to keep from using anything not available in the native OS wherever possible.

(It's only in the last 2 to 3 years that I feel confident enough that I will have most of the Powershell I need available to me, so I've begun to use it more Particularly for this type of issue)

So I spent several long hours through the night working on a version of the script which can replace the comments using native batch only.

This really took some doing as it has been at least a year ot two since I used this on anythign as complex as code which gives you all sorts of fun issues.

The below script should meet your needs using only native windows CMD Interpreter.

I have set the script to create a backup of the original files just in case I missed some scenario I didn't plan for.

I have the sample file I created and used and the example results are shown after the code below.

Fart.cmd Script:

REM Script: FART.cmd
REM Version: 0.9.3
REM Description: Replaces Text (Argument 2) with alternate Text (Argument 3) in File (Argement 1)
REM Example Usage: FART.cmd "C:\Admin\Stack_Exchange\40510701_FART\file.java" "abc();" "\\abc();"

@(
    SETLOCAL
    ECHO OFF
    SET "eLvl=0"
    SET "_FilePath=%~1"
    SET "_Find=%~2"
    SET "_Rep=%~3"
    SET "_ReFind=%~3"
    CALL :GetDateTime
)

CALL :Main

(
    ENDLOCAL
    Exit /b %eLvl%
)

:Main

    REM Set extra replace statement to keep commented matches at two comments depth if the replace string is a comment.
    IF /I "%_Rep:~0,2%" EQU "\\" (
        SET "_ReFind=\\%_Rep%"
    )

    REM Delete Temp File if it exists.
    DEL /F /Q "%_FilePath%.tmp"

    REM Make sure Delayed expantion is not turned on for the loop to interpret FindStr Correctly.
    REM Note:  Delayed expantion is diabled by default, however we're just being 'sure' as the FindStr prefix is needed to print blank lines correctly, so we can;t just use "type".
    SETLOCAL DISABLEDelayedExpansion

    FOR /F "Tokens=*" %%A IN ('Findstr /n "^" "%_FilePath%"') DO (

        SET "_Line=%%A"

        REM Enable Delayed expantion within the loop in order to process the line contents correctly.
        SETLOCAL ENABLEDelayedExpansion

        REM ECHO.
        REM Remove Prefix from Findstr.  (FindStr prefix is needed to print blank lines correctly)
        SET "_LineP=!_Line:*:=!"
        IF DEFINED _LineP (
            REM Replace + don't expand comments continually
            SET "_LineR=!_LineP:%_Find%=%_Rep%!"
            SET "_LineR=!_LineR:%_ReFind%=%_Rep%!"
        )
        REM ECHO.4
        REM ECHO.!_LineR!
        ECHO.!_LineR!>>"%_FilePath%.tmp"
        REM End the local delayed expantion environment while still within the loop.
        ENDLOCAL
    )

    REM End the local Non-Delayed expanion environement needed for the loop explicitly.
    ENDLOCAL

    REM Create a backup of the Original File for safety's sake.
    MOVE /Y "%_FilePath%" "%_FilePath%.%IsoDate%_%IsoTime%.bak"

    REM Move the temp file to replace the original File
    MOVE /Y "%_FilePath%.tmp" "%_FilePath%"
GOTO :EOF

:GetDateTime

    REM Note: I'm Tooting my own horn here, this took some doing:
    REM I created this Function to handle date and time across systems in different Regions.
    REM This gives the values both in their Zero Prefixed version, and in a version with the zero prefix stripped off so you can use it for calcuations.
    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 /a "#%%~a=1%%~A - (2%%~A-1%%~A)"
            SET /a "#%%~b=1%%~B - (2%%~B-1%%~B)"
            SET /a "#%%~c=1%%~C - (2%%~C-1%%~C)"
            SET "HH=%%~D"
            SET "Mn=%%~E"
            SET "SS=%%~F"
            SET "Ms=%%~G"
            SET /a "#HH=1%%~D - (2%%~D-1%%~D)"
            SET /a "#Mn=1%%~E - (2%%~E-1%%~E)"
            SET /a "#SS=1%%~F - (2%%~F-1%%~F)"
            SET /a "#Ms=1%%~G - (2%%~G-1%%~G)"
            SET /a "#TMinutes=((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E))"
            SET /a "#TSeconds=((((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E)))*60)+(1%%~F - (2%%~F-1%%~F))"
        )
    )
    SET "TTime=%HH%.%Mn%.%SS%"
    SET "IsoTime=%HH%.%Mn%.%SS%.%Ms%"
    SET "TDate=%yy%-%mm%-%dd%"
    SET "IsoDate=%yy%-%mm%-%dd%"
GOTO :EOF

Contents of the file I used for testing (Before change)

Hello there" Some stuff here"
"
""
{"orderNumber": "1476628690_2WOSU1OR"}<
more stuff here
the end
C:\Admin\Stack_Exchange\40071522

Powershell { $OldFile = get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" | %{$_ -replace 'abc();','\\abc();'}; $OldFile | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

etrsyabc();
abc();
ghuoyuo | %{8p'\\abc();',hio[);'}
Powefuyo-cytonttgyientt4S ftilyte.javahkjtfy | JIxsdO;{$_ FGTacsde 'abc(YUOYT$YY);','\\$abc(7)$;'}TYTY
\abc();
abc()
abc()
abc();
wf \\abc();
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
 $Find='abc\(\)\;'; $Replace=''

Last line befoere 2 blank lines

Contents of the file I used for testing (After change)

Hello there" Some stuff here"
"
""
{"orderNumber": "1476628690_2WOSU1OR"}<
more stuff here
the end
C:\Admin\Stack_Exchange\40071522

Powershell { $OldFile = get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" | %{$_ -replace '\\abc();','\\abc();'}; $OldFile | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }

etrsy\\abc();
\\abc();
ghuoyuo | %{8p'\\abc();',hio[);'}
Powefuyo-cytonttgyientt4S ftilyte.javahkjtfy | JIxsdO;{$_ FGTacsde 'abc(YUOYT$YY);','\\$abc(7)$;'}TYTY
\\\abc();
abc()
abc()
\\abc();
wf \\abc();
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
Powershell { $($(get-content "C:\Admin\Stack_Exchange\40510701_FART\file.java") -replace 'abc\(\)\;','\\abc();') -replace '\\\\\\*abc\(\)\;','\\abc();' | set-content "C:\Admin\Stack_Exchange\40510701_FART\file.java" }
 $Find='abc\(\)\;'; $Replace=''

Last line befoere 2 blank lines
Ben Personick
  • 3,074
  • 1
  • 22
  • 29
  • That's a pretty long script. I will try it and get back to you. Thanks for help :) – ashu Nov 15 '16 at 07:15
  • It's very difficult to accomplish what you're looking for with only native CMD scripting. Not impossible, but it takes a lot. The above script may not work in all scenarios, but it does comment the above text files as expected, and if there are some edge cases where this does not work, it can probably be expanded to handle them – Ben Personick Nov 16 '16 at 03:39
  • My humble apologies for not getting it back... I thought I have replied here. Thanks to my office network where we can refer SO but cant sign in/ up. Anyhow, the script idea was later dropped off. However, I have tested on system to check how good it is. It works and file did come out as expected. Though I had console saying "Could not found path/file.extension.tmp" and one instruction line saying how to use it. But yes, I still use this in my local system to get quick project setup. Thanks a lot for your help!! The thing I loved is it removed dependency even from the program I depended on.. – ashu Apr 14 '17 at 18:59
  • Glad this is very useful to you for your needs :) – Ben Personick Apr 14 '17 at 19:58