Bootstrap FreeKB - Ansible - Append, change, or remove a line in a file using the lineinfile module
Ansible - Append, change, or remove a line in a file using the lineinfile module

Updated:   |  Ansible articles

If you are not familiar with modules, check out Ansible - Getting Started with Modules.

There are a few different modules that can be used to modify a file.

  • blockinfile can be used to append, change, or remove a block of lines in a file
  • lineinfile can be used to append, change, or remove one or more lines in a file (this article)
  • replace can be used to change or remove one or more lines in a file.

By default, the line will be appended at the end of the file if the file does not already contain the line.

---
- hosts: all
  tasks:
  - name: append 'Hello World' to /tmp/foo.txt
    lineinfile:
      path: /tmp/foo.txt
      line: "Hello World"
...

 

If the target file exists and does not contain "Hello World", "changed" should be returned.

TASK [append 'Hello World' to /tmp/foo.txt] 
changed: [server1.example.com]

 

If the target file exists and already contains line "Hello World", "ok" should be returned and Hello World will not be appended to the file.

TASK [append 'Hello World' to /tmp/foo.txt] 
ok: [server1.example.com]

 

The debug module can make this even more apparent.

---
- hosts: all
  tasks:
  - name: append 'Hello World' to /tmp/foo.txt
    lineinfile:
      path: /tmp/foo.txt
      line: "Hello World"
    register: out

  - debug:
      var: out
...

 

If the target file exists and does not contain "Hello World", "changed" should be true and msg should contain "line added".

ok: [server1.example.com] => {
    "out": {
        "backup": "", 
        "changed": true, 
        "diff": [
            {
                "after": "", 
                "after_header": "/tmp/foo.txt (content)", 
                "before": "", 
                "before_header": "/tmp/foo.txt (content)"
            }, 
            {
                "after_header": "/tmp/foo.txt (file attributes)", 
                "before_header": "/tmp/foo.txt (file attributes)"
            }
        ], 
        "failed": false, 
        "msg": "line added"
    }
}

 

If the target file exists and already contains line "Hello World", changed should be false and msg should be empty.

ok: [server1.example.com] => {
    "out": {
        "backup": "", 
        "changed": false, 
        "diff": [
            {
                "after": "", 
                "after_header": "/tmp/foo.txt (content)", 
                "before": "", 
                "before_header": "/tmp/foo.txt (content)"
            }, 
            {
                "after_header": "/tmp/foo.txt (file attributes)", 
                "before_header": "/tmp/foo.txt (file attributes)"
            }
        ], 
        "failed": false, 
        "msg": ""
    }
}

 

AVOID TROUBLE

If the target file does not exist, lineinfile may cause the play to fail fatal.

For this reason, you will almost always want to use the create: true parameter, so that the file is created if it does not exist. Or use the stat module to determine if the file exists, and then used the when parameter to only execute the task when the file exists.

fatal: [server1.example.com]: FAILED! => {
  "changed": false,
  "msg": "Destination /tmp/foo.txt does not exist !",
  "rc": 257
}

 

The create option can be used to create the file if it does not exist.

Or the file module can be used to create the file.

Or the stat module can be used to determine if the file exists and the when parameter can be used to only execute the task when the file exists.

Or ignore_errors can be used.

---
- hosts: all
  tasks:
  - name: append 'Hello World' to /tmp/foo.txt
    lineinfile:
      path: /tmp/foo.txt
      line: "Hello World"
      create: true
...

 

with_items can be used to append multiple lines to the file.

---
- hosts: all
  tasks:
  - name: append lines to /tmp/foo.txt
    lineinfile:
      path: /tmp/foo.txt
      line: "{{ item }}"
      create: true
    with_items:
    - Hello World
    - foo
    - bar
...

 

insertafter: EOF can be used to append new lines to the bottom of the file which is the default behavior thus this parameter isn't required.

- name: append 'World' to the end of /tmp/foo.txt
  lineinfile:
    path: /tmp/foo.txt
    line: World
    insertafter: EOF

 

Or, you can use a regular expression. Let's say foo.txt contains the following:

Hello
World

 

The following will append "example" after the line beginning with Hello.

---
- hosts: all
  tasks:
  - name: append 'example' after line beginning with 'Hello'
    lineinfile:
      path: /tmp/foo.txt
      line: example
      insertafter: ^Hello
...

 

Running this play should update foo.txt to have the following.

Hello
example
World

 

insertbefore: BOF can be used to append to the beginning of the file (BOF).

---
- hosts: all
  tasks:
  - name: append 'World' to the beginning of /tmp/foo.txt
    lineinfile:
      path: /tmp/foo.txt
      line: World
      insertbefore: BOF
...

 

In this example, state: present is used so that "new line" is appended if the file does not currently contain any lines matching "new line" which is the default behavior thus this parameter isn't required. If there is already a line matching "new line", nothing will be appended.

- name: append new line EOF if doesn't exist
  lineinfile:
    path: /tmp/foo.txt
    line: "new line"
    state: present

 

In this example, line is used to replace the last line containing "old line" with "new line". If the file contains two or more lines containing "old line", only the last line containing "old line" will be updated to "new line". For this reason, the replace module is typically used to update a text in a file, as the replace module would replace every line containing "old line" with "new line".

- name: replace old line with new line
  lineinfile:
    path: /tmp/foo.txt
    regexp: "old line"
    line: "new line"

 

Append to an existing line

Let's say foo.txt contains "Hello World". Here is how you would append "example" after Hello World.

- lineinfile:
    path: /tmp/foo.txt
    backrefs: true
    regexp: '^(old line)$'
    line: '\1 example'

 

Remove lines

regexp and state: absent can be used to remove lines matching the regular expression. In this example, lines containing "Hello World" will be removed from the /tmp/foo.txt file.

- name: remove new line
  lineinfile:
    path: /tmp/foo.txt
    regexp: "Hello World"
    state: absent

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter ac103e in the box below so that we can be sure you are a human.