06 - Loops¶
Learn how to iterate over lists and files to avoid repetition.
What You'll Learn¶
- Iterating over lists with
with_items - Iterating over files with
with_filetree - Using loop variables:
{{ item }},{{ index }},{{ first }},{{ last }} - Accessing file properties in loops
Quick Start¶
cd examples/06-loops
# Run list iteration example
mooncake run --config with-items.yml
# Run file tree iteration example
mooncake run --config with-filetree/config.yml
Examples Included¶
1. with-items.yml - List Iteration¶
Iterate over lists of items:
- vars:
packages:
- neovim
- ripgrep
- fzf
- name: Install package
shell: brew install {{ item }}
with_items: "{{ packages }}"
What it does:
- Defines lists in variables
- Installs multiple packages
- Creates directories for multiple users
- Creates user-specific config files
2. with-filetree/ - File Tree Iteration¶
Iterate over files in a directory:
- name: Copy dotfile
shell: cp "{{ item.src }}" "/tmp/backup/{{ item.name }}"
with_filetree: ./files
What it does:
- Iterates over files in
./files/directory - Copies dotfiles to backup location
- Filters directories vs files
- Displays file properties
Key Concepts¶
List Iteration (with_items)¶
- vars:
users: [alice, bob, charlie]
- name: Create user directory
file:
path: "/home/{{ item }}"
state: directory
with_items: "{{ users }}"
This creates:
/home/alice/home/bob/home/charlie
File Tree Iteration (with_filetree)¶
- name: Process file
shell: echo "Processing {{ item.name }}"
with_filetree: ./dotfiles
when: item.is_dir == false
Available properties:
item.src- Full source pathitem.name- File nameitem.is_dir- Boolean, true if directory
Loop Variables¶
Both with_items and with_filetree provide additional loop variables:
- vars:
packages: [git, vim, tmux]
- name: "Installing {{index + 1}}/{{packages|length}}: {{item}}"
shell: |
echo "Package: {{item}}"
echo "Index: {{index}}"
echo "First: {{first}}"
echo "Last: {{last}}"
brew install {{item}}
with_items: "{{packages}}"
Available loop variables:
{{ item }}- Current item (forwith_items) or file object (forwith_filetree){{ index }}- Zero-based iteration index (0, 1, 2, ...){{ first }}- Boolean, true for first iteration{{ last }}- Boolean, true for last iteration
Example use cases:
# Progress counter
- name: "[{{index + 1}}/3] Processing {{item}}"
shell: process {{item}}
with_items: [a, b, c]
# First-only setup
- name: Initialize on first item
shell: mkdir -p /tmp/output
with_items: "{{files}}"
when: first == true
# Last-only cleanup
- name: Cleanup after last item
shell: echo "All done!"
with_items: "{{files}}"
when: last == true
Filtering in Loops¶
Skip directories:
- name: Copy files only
shell: cp "{{ item.src }}" "/tmp/{{ item.name }}"
with_filetree: ./files
when: item.is_dir == false
Real-World Use Cases¶
with_items:
- Installing multiple packages
- Creating multiple users/groups
- Setting up multiple services
- Deploying to multiple servers
with_filetree:
- Managing dotfiles
- Deploying configuration directories
- Backing up files
- Processing file collections
Testing¶
# List iteration
mooncake run --config with-items.yml
# Check created files
ls -la /tmp/users/
# File tree iteration
mooncake run --config with-filetree/config.yml
# Check backed up files
ls -la /tmp/dotfiles-backup/
Next Steps¶
Continue to 07-register to learn about capturing command output.