#!/bin/bash set -euo pipefail # Regex for valid docker compose file names COMPOSE_REGEX='^(docker-compose|compose)\.ya?ml$' # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Dry-run mode DRY_RUN=0 # Parse arguments while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN=1 shift ;; *) ROOT_DIR="$1" shift ;; esac done # Prompt for directory if not provided if [[ -z "${ROOT_DIR:-}" ]]; then echo -e "${YELLOW}No root directory provided.${NC}" read -e -p "Enter the root directory to search: " ROOT_DIR fi # Validate directory if [[ ! -d "$ROOT_DIR" ]]; then echo -e "${RED}Error: '$ROOT_DIR' is not a valid directory.${NC}" exit 1 fi echo -e "${GREEN}Searching for docker-compose files in: $ROOT_DIR${NC}" processed=() skipped=() find "$ROOT_DIR" -maxdepth 1 -type d -print0 | while IFS= read -r -d $'\0' dir; do # Skip the root directory itself if you want only subdirs # [[ "$dir" == "$ROOT_DIR" ]] && continue compose_file="" for file in "$dir"/*; do filename=$(basename "$file") if [[ $filename =~ $COMPOSE_REGEX ]]; then compose_file="$file" break fi done if [[ -n "$compose_file" ]]; then echo -e "${GREEN}Processing: $dir ($compose_file)${NC}" processed+=("$dir") if [[ $DRY_RUN -eq 0 ]]; then ( cd "$dir" || exit 1 docker compose -f "$compose_file" pull && docker compose -f "$compose_file" up -d ) else echo -e "${YELLOW}[Dry-run] Would run: docker compose -f \"$compose_file\" pull && docker compose -f \"$compose_file\" up -d${NC}" fi else echo -e "${YELLOW}No compose file found in: $dir${NC}" skipped+=("$dir") fi done echo -e "\n${GREEN}Completed processing all subdirectories.${NC}" echo -e "${GREEN}Processed directories:${NC}" for d in "${processed[@]}"; do echo " $d" done if [[ ${#skipped[@]} -gt 0 ]]; then echo -e "${YELLOW}Skipped directories (no compose file found):${NC}" for d in "${skipped[@]}"; do echo " $d" done fi