# Passing multiple file types in a shell command through a loop

**URL:** <https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825>\
**Category:** Get Help\
**Created:** [July 10, 2025, 6:26pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825 "2025-07-10T18:26:06Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![trt757](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@trt757](https://forum.ansible.com/u/trt757)\
**Post date:** [July 10, 2025, 6:26pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/1 "2025-07-10T18:26:07Z")

</div>

I’m still having a lot of trouble understanding how a loop handles passing multiple files through a shell command.

I have a directory on a CA Server: certdir  
Inside ‘certdir’ are directories named for all of my hosts (only have two right now for testing speed) - host1 and - host2

Inside each of these dirs are host1.our-domain.csr and host1.our-domain.req files

I’m trying to pass both of these files in this shell command: openssl ca -batch -config {{ dir }}.our-domain.req -extensions server\_cert -days 720 -notext -md sha256 -in {{ dir }}.our-domain.csr -out {{ dir }}.dgs.mil.crt

What I’m hoping to get out of this command is a file created in each host directory, ex: host1.our-domain.crt, host2.our-domain.crt, in their respective host directories and so on.

I’m registering each host directory in an earlier part of the play as “dir”. I’m registering the csr and req files as well (csr and req) respectively.

Here’s the part of the play that errors out:

- name: create crt file  
ansible.builtin.shell: openssl ca -batch -config {{ dir }}.our-domain.req -extensions server\_cert -days 720 -notext -md sha256 -in {{ dir }}.our-domain.csr -out {{ dir }}.dgs.mil.crt  
loop: “{{ csr.files | map(attribute=‘path’) | list }}”  
loop\_control:  
label: "{{ item | basename }}  
when: out\_crt == False (I only want the shell command to run if a crt file doesn’t already exist)

The above is just the latest iteration of what I’ve tried. I suspect it has something to do with “item” is the reason it’s failing. I don’t really even get an error. It just keeps skipping that task in the play with this: skipping: [CA\_host\_dir] . So it’s not even referencing the host dirs, just the CA dir.

Can someone provide some advice?

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [July 10, 2025, 10:12pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/2 "2025-07-10T22:12:37Z")

</div>

It could be that your boolean comparison is not working properly. Try `when: out_crt` or `when: out_crt | bool` instead.

Additionally, there should be `{{ item }}` or a variable derived from `{{ item }}` somewhere in your command or you will run the same exact command for each item which is meaningless. What is the value of `csr.files`?

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [July 11, 2025, 2:39pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/3 "2025-07-11T14:39:07Z")

</div>

I think you are fundamentally misunderstanding loops, they run the shell command multiple times, once per item, templating and using the current `item` each time. Since it is completely skipped you either have an empty list or your `when` condition is returning `False`, as has already been pointed out.

In general also adding `-vvv` output would be helpful in debugging your issues.

---

<div class="post-metadata">

**Author:** ![trt757](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@trt757](https://forum.ansible.com/u/trt757)\
**Post date:** [July 11, 2025, 2:56pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/4 "2025-07-11T14:56:53Z")

</div>

All I’m asking is how to pass two variables into a shell command and loop that command through all the directories. I can find many working examples of where this is done with only one variable, but how does the play change when it’s two? I can’t find any examples of that.

My playbook is on a closed network so I can’t spend too much time typing the whole thing out here. Most of it is pretty easy. Find the host directories inside a directory on the CA server called “certdir”. I register all three of those as variables ( out\_dir, out\_csr, and out\_req). For a sanity check I put a debug/msg print statement in the play just so I can see on-screen that yes, ansible understands that there are multiple host directories, and it shows me the files in the form - host.our-domain.csr and host.our-domain.key It does that just fine.

All that was simple.

But how do you get Ansible to understand passing two of the above variables in a command like:

openssl ca -batch -config $out\_req -extensions server\_cert -days 730 -notext -md sha256 -in $out\_csr -out $out\_dir.crt ( I understand that Ansible doesn’t use $variable, that is a bash form of variable, I just typed it like that for simplicity).

I guess it’s actually 3 variables since I need the cert to pick up the name of the host.

I’m close to just giving up on this part of the playbook and hand-jamming that above command. The playbook will still save time moving files around, creating an rsyslog.conf from template and pushing that out to all the workstations, and restarting the service.

---

<div class="post-metadata">

**Author:** ![trt757](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@trt757](https://forum.ansible.com/u/trt757)\
**Post date:** [July 11, 2025, 3:02pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/5 "2025-07-11T15:02:12Z")

</div>

It’s actually not that bad if it’s just one variable:

```auto
 - name: Find CSR files
      ansible.builtin.find:
        paths: "{{ playbook_dir }}"
        file_type: file
        patterns: '*.csr'
        recurse: yes
      register: csr

    - name: Set file names into new variable
      set_fact:
        CSR: "{{ csr.files | map(attribute='path') | map('basename') | list }}"

    - name: Print CSR variable
      debug:
        msg: "Print result of CSR search: {{ CSR }}"

    - name: Test variable usage against the found CSR files
      ansible.builtin.shell:
        cmd: "openssl req -text -noout -verify -in {{ item }}"
      loop: "{{ CSR }}"

```

But the above was just to learn about loops to see if a shell command would act on a varibale, and it did. I did add a statement to print the output of the openssl verify

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [July 11, 2025, 3:05pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/6 "2025-07-11T15:05:46Z")

</div>

There is no difference between using 1 or 100 variables, also you don’t pass variables, you template (on the ansible machine) using variables and pass the resulting action to the target. You are using a single variable `{{dir}}` not 2 or 3. Also I don’t see how you create `dir`, but i suspect you just need a `vars` entry:

```auto
- name: create crt file
  ansible.builtin.shell: openssl ca -batch -config {{ dir }}.our-domain.req -extensions server_cert -days 720 -notext -md sha256 -in {{ dir }}.our-domain.csr -out {{ dir }}.dgs.mil.crt
  loop: “{{ csr.files | map(attribute=‘path’) | list }}”
  vars:
     dir: '{{item|dirname}}' # or whatever dir is supposed to be PER item, having the same across all items keeps it as a the same command N times

```

That aside from your skip issue, which I cannot help without more information.

---

<div class="post-metadata">

**Author:** ![trt757](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@trt757](https://forum.ansible.com/u/trt757)\
**Post date:** [July 11, 2025, 4:00pm UTC](https://forum.ansible.com/t/passing-multiple-file-types-in-a-shell-command-through-a-loop/43825/7 "2025-07-11T16:00:03Z")

</div>

I’m creating dir in the following manner:

- name: Playbook  
hosts: CA  
become: yes  
gather\_facts: no  
vars:  
cert\_dir: /etc/ws\_certs  
csr: “{{out\_csr.files | map(attribute=‘path’ | map(‘basename’) }}”  
dir: “{{out\_dir.files | map(attribute=‘path’ | map(‘basename’) }}”  
req: “{{out\_req.files | map(attribute=‘path’ | map(‘basename’) }}”  
crt: “{{out\_crt.files | map(attribute=‘path’ | map(‘basename’) }}”

I wanted to register cert because I want to add a when statement to not run the openssl command if a cert if found in cert\_dir
