Bash for Oracle DBAs قسمت سوم حلقه‌ها در Bash

در دو قسمت قبل یاد گرفتیم:

اما در عمل، کارهای مدیریتی معمولاً روی یک فایل انجام نمی‌شوند.

بلکه روی:

  • چندین فایل log
  • چندین اسکریپت
  • چندین دایرکتوری
  • چندین کاربر

برای انجام کارهای تکراری در Bash از حلقه‌ها (Loops) استفاده می‌کنیم.

مهم‌ترین حلقه در اسکریپت‌های مدیریتی Linux:

for

ساختار پایه حلقه for

ساختار کلی:

for variable in list
do
   commands
done

مثال ساده:

for i in 1 2 3
do
  echo "Number: $i"
done

خروجی:

Number: 1
Number: 2
Number: 3

حلقه روی فایل‌ها (کاربرد واقعی DBA)

یکی از رایج‌ترین کاربردها، اجرای عملیات روی چند فایل است.

مثلاً بررسی همه فایل‌های .log در یک مسیر:

for file in /var/log/*.log
do
  echo "Checking $file"
done

در اینجا:

*.log

به آن globbing می‌گویند.

یعنی Bash تمام فایل‌هایی که با این الگو match می‌شوند را جایگزین می‌کند.


ترکیب for با شرط

فرض کنید بخواهیم فقط فایل‌هایی را پردازش کنیم که واقعاً وجود دارند.

for file in /var/log/*.log
do
  if [[ -f "$file" ]]; then
    echo "Processing $file"
  fi
done

این ترکیب for + if پایه بسیاری از اسکریپت‌های automation است.


اجرای چند اسکریپت پشت سر هم

فرض کنید چند اسکریپت در یک دایرکتوری دارید و می‌خواهید همه را اجرا کنید.

for script in /opt/scripts/*.sh
do
  if [[ -x "$script" ]]; then
    echo "Executing $script"
    "$script"
  fi
done

در اینجا:

  • ابتدا بررسی می‌کنیم فایل executable است (-x)
  • سپس آن را اجرا می‌کنیم

این الگو در اسکریپت‌های ماژولار بسیار رایج است.


استفاده از {} برای تولید عدد

گاهی می‌خواهیم یک کار را تعداد مشخصی بار انجام دهیم.

for i in {1..5}
do
  echo "Run number $i"
done

این روش به آن brace expansion می‌گویند.


حلقه روی خروجی یک دستور

یکی از کاربردی‌ترین حالت‌ها:

for user in $(cut -d: -f1 /etc/passwd)
do
  echo "User: $user"
done

اینجا:

  • cut -d: فایل passwd را بر اساس : جدا می‌کند
  • فقط ستون اول (نام کاربر) را می‌گیرد
  • حلقه روی همه کاربران اجرا می‌شود

⚠ نکته حرفه‌ای:

این روش در فایل‌هایی که فاصله دارند می‌تواند مشکل ایجاد کند. در نسخه‌های پیشرفته‌تر از while read استفاده می‌شود که در مقاله‌های بعدی بررسی می‌کنیم.


استفاده از break

برای خروج از حلقه:

for i in {1..10}
do
  if [[ $i -eq 5 ]]; then
    break
  fi
  echo $i
done

حلقه در عدد 5 متوقف می‌شود.


استفاده از continue

برای رد کردن یک iteration:

for i in {1..5}
do
  if [[ $i -eq 3 ]]; then
    continue
  fi
  echo $i
done

عدد 3 چاپ نمی‌شود.


مثال عملی واقعی

فرض کنید می‌خواهیم بررسی کنیم کدام فایل‌های یک دایرکتوری permission ناامن دارند.

for file in /tmp/*
do
  if [[ -f "$file" ]]; then
    mode=$(stat -c %a "$file")

    if [[ "$mode" == "777" ]]; then
      echo "Insecure permission: $file"
    fi
  fi
done

در این مثال:

  • روی همه فایل‌های /tmp loop می‌زنیم
  • permission را می‌خوانیم
  • اگر 777 بود هشدار می‌دهیم

این دقیقاً همان نوع منطقی است که در اسکریپت‌های امنیتی استفاده می‌شود.


اشتباه رایج

❌ اشتباه:

for file in /var/log/*.log
do
  echo $file
done

✅ بهتر:

for file in /var/log/*.log
do
  echo "$file"
done

همیشه متغیرها را در کوتیشن قرار دهید.


تمرین

یک اسکریپت بنویسید که:

  1. روی تمام فایل‌های /etc/*.conf loop بزند
  2. بررسی کند کدام فایل‌ها قابل خواندن نیستند
  3. نام آن‌ها را چاپ کند