I'd like to write a bash script that essentially automates this process:

vi filename.sh

(open "filename.sh" using vi)

add the following 2 lines:

export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

and save those changes


Basically I want to add these in jenkins file for automation

  • 2
    Where do you want to add those lines? At the beginning, at the end, at a specific position? Edit your question to include this. This is not a job for vi. – Panki Oct 17 '19 at 9:57
  • I am creating a new file and adding these lines – SAHIL Oct 17 '19 at 10:03
  • 1
    Can't Jenkins transfer files? Why not create that file once and transfer it? – Jeff Schaller Oct 17 '19 at 10:07

vi is by definition a visual editor.

In this case it's probably better to use some other means.

If you only want to append those lines, do something like:

cat >> filename.sh <<'EOF'
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

This will also work if the file doesn't exist yet.

If you want those lines added at the beginning, you can use ed which is a line-oriented editor:

ed filename.sh <<'EOF'
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

This instructs ed to insert lines at line 1; the solitary dot . on the line indicates the end of input, so insertion stops there. Finally the file is written (w) and the edit session quitted (q).

If you insist on using ed even if the file doesn't exist yet (in which case I would use the cat example above), you can use this:

ed filename.sh <<'EOF'
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}
w filename.sh

The main difference is that you don't pass a line number with the i insert command, as there are no lines yet; and you pass a filename to the w write command which is the new file.

sed can also be used, but for such tasks I find ed easier to use (and to read what's happening).

  • after doing ed getting No such file or directory error: [root@fcired67 ~]# ed /etc/s1.sh <<'EOF' > 1i > export GRADLE_HOME=/opt/gradle/gradle-5.2.1 > export PATH=${GRADLE_HOME}/bin:${PATH} > . > w > q > EOF /etc/s1.sh: No such file or directory – SAHIL Oct 17 '19 at 10:11
  • That sounds like the file /etc/s1.sh does not exist. The file needs to exist before ed can edit it. – wurtel Oct 17 '19 at 10:44
  • yes, first have to create that file then needs to add the lines so what changes should i add now to make it work? – SAHIL Oct 17 '19 at 10:47
  • I've edited my answer to handle the case where the file doesn't exist yet. – wurtel Oct 17 '19 at 13:03
  • @wurtel you could have been even better IMHO if you cut your examples a bit down and concentrate on these three steps in OQ; 1)open file 2)operate data 3)write file OQ says automate, and you say visual editor etc. maybe it is a small algorithm where a filetest and a sed line is needed --- more of: it depends: on A, B and C. Then you have solutions X, Y, Z, e.g. Y: – rastafile Oct 17 '19 at 13:23

Automated scripting can be done using ed

like ed < edit.sed filename.pdf

For more, you can visit this tutorial.

  • Also, I found a similar question Here on askUbuntu – champion-runner Oct 18 '19 at 12:47
  • For inserting at a specific line that is fine. sed is a tool for that. But from what we know, appending at the end is enough. Two lines (in a file, I propose) and a file: not so difficult to concatenate with cat, if not for that in-place problem, which can be solved with >> redirection. – rastafile Oct 18 '19 at 14:00

I would also do it the way @wurtel is suggesting, but if for some reason you really want to do it with vi, add the following to your $HOME/.vimrc file:

function AddVars()
    let line1 = "export GRADLE_HOME=/opt/gradle/gradle-5.2.1"
    let line2 = "export PATH=${GRADLE_HOME}/bin:${PATH}"
    call append(line('$'), line1)
    call append(line('$'), line2)

And then call vi with using the -c option like this: vi filename.sh -c "call AddVars()"

  • If you prefer to add the lines at the beginning of the file, change call append(line('$'), line1) with call append(line('1'), line2) and call append(line('$'), line2) with call append(line('$'), line1) – LincolnP Oct 17 '19 at 10:43
  • you append at the end; OQ says "add" (and he is in vi). See comment at wurtel. And of course you could aliias that long vi command further. – rastafile Oct 17 '19 at 13:37
  • Thank you @rastafile, good point – LincolnP Oct 17 '19 at 18:22
  • just right now I posted a answer myself!. Thx to cas, see his bark. I like your vim function a lot, but not for this Q. Save it for smth more complex. – rastafile Oct 17 '19 at 18:26

Jenkinsfile is a kind of addition to version control systems. It works with pipelines and textfiles.

This is a nice example to demonstrate the interactive vs. the programmed approach, i.e. the differences.

The process can be split in three parts, as OQ points out:

1) open FILE in a interactive (and thus: visual) editor

2) ADD 2 lines. Line noise lines. Add (or insert) where?

3) Save. Mentioned extra :wq. But we dont do key macros here.

Now you translate to automated. I keep it simple first, wurtel's HERE document is a good start. But is this a finished "solution"? I propose:

Create a file with these two lines alone. They are constant, and they contain dollar signs. Call it gradle-lines for now. Good investment anyway:

export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

Now you can

cat gradle-lines >>filename.sh

And after

alias grad-append='cat gradle-lines >>' you can type

grad-ap(TAB) filenam(TAB)

...to run an alias with a filename. Any filename.

grad-append filename.sh is short for cat gradle-lines >> filename.sh

I have nothing else really to show! (So simple)

A solution with sed -i seems an alternative. A must if you plan to insert these lines at a special place. Besides perl etc., but that is another caliber and really not needed here.

Anyway it's two slightly different elemantary steps: appending >> and aliasing.

But Jenkinspipe and >> of a two-line file should be n.p. Need more specs for that.


I tested all this. I mean I tested much more until I realized a file with the two lines and a >> suffice. Nasty Q!

I started this Q by commenting quite positively on wurtel's answer; here is his main solution I mention above, the HERE document. I have to give credit to him, formally. I swear I took a detour involving info sed and tmpf=mktemp and even cp $(mktemp) but then append to which file? Here wurtel's HERE:

If you only want to append those lines, do something like:

cat >> filename.sh <<'EOF'
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

This will also work if the file doesn't exist yet.

If you put this in a script or function it would be called grad-append as in my solution. But this one is a function (luckily) because it needs (sadly) a positional parameter $1. "filename.sh" is now hard-coded.

And that here document also lacks modularity; function and data are mixed. It could be perfect for certain situations. But my variation is more flexible and direct.

What if he -- only once in while -- wants to :read gradle-lines into vim interactively? My solution has reusable modules as side effect.

  • Actually I wanted to do cat FILE gradle-lines >FILE But there is a problem with that. My three-step-intro is a big announcement of not much --- somehow demonstrates this simple operation, and how a Q can mislead you. – rastafile Oct 17 '19 at 18:32
  • perl explains it's -i (edit in-place) so: It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements. – rastafile Oct 18 '19 at 12:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.