سكربتات Shell في Linux: المتغيرات والشروط والحلقات
في درس الصلاحيات كتبت أول سكربت: ملف فيه أوامر تُنفَّذ بالترتيب. لكن السكربت الحقيقي أذكى من قائمة أوامر: يستقبل مدخلات، ويتخذ قرارات، ويكرر العمل على عشرات الملفات. في هذا الدرس الأخير ستتعلم لغة Bash نفسها: المتغيرات والشروط والحلقات والدوال، وتجمعها في سكربت نسخ احتياطي تستخدمه فعلاً.
السكربت مثل وصفة طبخ تكتبها مرة واحدة: بعدها يكفي أن تقول «نفّذ الوصفة» بدل أن تتذكر الخطوات في كل مرة.
تذكير: هيكل السكربت
Section titled “تذكير: هيكل السكربت”#!/bin/bashname="Sara"echo "Hello, $name!"echo "You have ${#name} letters in your name."echo 'Single quotes: $name'chmod +x hello.sh./hello.shHello, Sara!You have 4 letters in your name.Single quotes: $name- السطر الأول
#!/bin/bashيحدد المفسّر، وchmod +xيجعل الملف قابلاً للتنفيذ. name="Sara": تعريف متغير. بلا مسافات حول علامة=.$name: قراءة قيمته، و${#name}عدد حروفه.- علامات التنصيص المزدوجة تستبدل المتغيرات بقيمها، والمفردة تبقي النص حرفياً.
ناتج أمر داخل متغير
Section titled “ناتج أمر داخل متغير”الصيغة $(...) تشغّل أمراً وتضع ناتجه مكانها:
files=$(ls .. | wc -l)echo "count: $files"count: 10والحسابات على الأعداد الصحيحة تُكتب داخل $((...)):
x=5; y=3echo $((x * y)) $((x / y)) $((x % y))15 1 2القسمة هنا صحيحة: 5 على 3 تعطي 1، والباقي 2.
معاملات السكربت
Section titled “معاملات السكربت”ما تكتبه بعد اسم السكربت يصله في متغيرات خاصة:
#!/bin/bashecho "Script: $0"echo "First: $1"echo "Second: $2"echo "Count: $#"echo "All: $@"./greet.sh Omar LailaScript: ./greet.shFirst: OmarSecond: LailaCount: 2All: Omar Laila| المتغير | المعنى |
|---|---|
$1 و $2 … |
المعامل الأول والثاني وهكذا |
$0 |
اسم السكربت نفسه |
$# |
عدد المعاملات |
$@ |
كل المعاملات معاً |
$? |
رمز خروج آخر أمر |
ولسؤال المستخدم أثناء التشغيل استخدم read: السطر read -p "What is your name? " name يطبع السؤال، وينتظر الإجابة، ويخزنها في المتغير name.
الشروط: if
Section titled “الشروط: if”#!/bin/bashif [ $# -eq 0 ]; then echo "Usage: $0 <file>" exit 1fi
if [ -f "$1" ]; then lines=$(wc -l < "$1") echo "$1 exists and has $lines lines"elif [ -d "$1" ]; then echo "$1 is a directory"else echo "$1 not found"fi./check.sh./check.sh ../scores.txt./check.sh ../logs./check.sh nothing.txtUsage: ./check.sh <file>../scores.txt exists and has 6 lines../logs is a directorynothing.txt not found- الشرط يُكتب بين
[و]مع مسافة إلزامية بعد الأول وقبل الثاني. thenتبدأ الجسم، وfi(كلمةifمعكوسة) تنهيه.exit 1: اخرج من السكربت برمز خطأ. تذكّر من درس العمليات: الصفر نجاح وغيره فشل.
أهم الفحوص:
| الفحص | يتحقق إذا |
|---|---|
-f path |
المسار ملف موجود |
-d path |
المسار مجلد موجود |
-e path |
المسار موجود (أي نوع) |
-z "$s" |
النص فارغ |
"$a" = "$b" |
النصان متساويان، و != للاختلاف |
$a -eq $b |
العددان متساويان، و -ne للاختلاف |
-gt و -lt |
أكبر من، أصغر من |
-ge و -le |
أكبر من أو يساوي، أصغر من أو يساوي |
مقارنة الأرقام بالحروف (-gt) لا بالرموز (>)، لأن > في الطرفية تعني إعادة التوجيه إلى ملف!
#!/bin/bashscore=$1if [ "$score" -ge 85 ]; then echo "Excellent"elif [ "$score" -ge 70 ]; then echo "Good"else echo "Needs work"fiتشغيله بـ ./grade.sh 92 يطبع Excellent، وبـ 75 يطبع Good، وبـ 40 يطبع Needs work.
الحلقات: for و while
Section titled “الحلقات: for و while”#!/bin/bashfor fruit in apple banana mango; do echo "I like $fruit"done
for i in {1..3}; do echo "Round $i"done
count=3while [ $count -gt 0 ]; do echo "Countdown: $count" count=$((count - 1))doneecho "Go!"I like appleI like bananaI like mangoRound 1Round 2Round 3Countdown: 3Countdown: 2Countdown: 1Go!for متغير in قائمة; do ... done: يكرر الجسم لكل عنصر في القائمة.{1..3}تولّد الأرقام من 1 إلى 3.while [ شرط ]; do ... done: يكرر ما دام الشرط متحققاً.
والاستخدام الأهم للحلقة for: المرور على ملفات، مع النجمة التي تعرفها:
#!/bin/bashfor file in ../logs/*.log ../scores.txt; do lines=$(wc -l < "$file") echo "$file: $lines"done../logs/app.log: 8../scores.txt: 6هكذا تعالج مئة ملف بثلاثة أسطر: تغيير أسمائها، أو ضغطها، أو البحث فيها.
الدوال
Section titled “الدوال”#!/bin/bashsay_hello() { echo "Hello, $1!"}
add() { echo $(($1 + $2))}
say_hello "Mona"say_hello "Ahmed"result=$(add 7 5)echo "7 + 5 = $result"Hello, Mona!Hello, Ahmed!7 + 5 = 12الدالة تستقبل معاملاتها في $1 و $2 مثل السكربت تماماً، وتُستدعى باسمها بلا أقواس. ولأخذ نتيجتها تطبعها الدالة بـ echo وتلتقطها بـ $(...).
مثال متكامل: نسخ احتياطي
Section titled “مثال متكامل: نسخ احتياطي”#!/bin/bash# backup.sh: copy a folder into backups/ with today's datesource_dir=$1backup_dir="backups"stamp=$(date +%Y-%m-%d)
if [ ! -d "$source_dir" ]; then echo "Error: $source_dir is not a directory" exit 1fi
mkdir -p "$backup_dir"target="$backup_dir/$(basename "$source_dir")-$stamp"cp -r "$source_dir" "$target"
files=$(find "$target" -type f | wc -l)echo "Backed up $files files to $target"./backup.sh ../logs./backup.sh ../nothingBacked up 2 files to backups/logs-2026-11-12Error: ../nothing is not a directoryفي خمسة عشر سطراً جمعنا كل ما تعلمته: معامل من المستخدم، وناتج أمر date في متغير، وفحص بـ if مع ! للنفي، ورمز خروج عند الخطأ، وأوامر mkdir و cp و find و wc من الدروس السابقة.
جرّب بنفسك
Section titled “جرّب بنفسك”- اكتب سكربت
info.shيطبع اسم المستخدم (whoami)، والمجلد الحالي، وعدد الملفات فيه. - اكتب سكربت
even.shيستقبل رقماً ويطبع هل هو زوجي أم فردي (تلميح:$(( $1 % 2 ))). - اكتب سكربت يمر على كل ملفات
.txtفي المجلد الحالي ويطبع اسم كل ملف وعدد كلماته. - تحدٍّ: عدّل
backup.shليرفض العمل برسالة واضحة إذا لم يُعطَ أي معامل، وليطبع رسالة مختلفة إذا كانت النسخة موجودة مسبقاً.
أخطاء شائعة
Section titled “أخطاء شائعة”- مسافات حول
=:name = Saraيعطيname: command not found، لأن Bash يظنnameأمراً. اكتبname=Sara. - نسيان المسافات داخل الأقواس:
[$a -eq 1]خطأ. الصحيح[ $a -eq 1 ]. - متغير بلا علامات تنصيص: إذا كان
$aفارغاً فإن[ $a = "x" ]يعطيunary operator expected. اكتب دائماً[ "$a" = "x" ]، وكذلك مع أسماء الملفات التي قد تحتوي مسافات. - نسيان
chmod +x: يعطيPermission deniedعند التشغيل بـ./script.sh.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
شغّلت ./deploy.sh web 8080. ما قيمة $2 داخل السكربت؟
المعاملات مرقمة بالترتيب: $1 هي web و $2 هي 8080، و $0 اسم السكربت.
سؤال
أي شرط يفحص أن المتغير count أكبر من 10 في Bash؟
مقارنة الأرقام بـ -gt، أما الرمز > فيعني إعادة التوجيه إلى ملف.
الخلاصة
Section titled “الخلاصة”name=valueبلا مسافات، و$nameللقراءة، و$(command)لناتج أمر، و$((...))للحساب.$1و$2معاملات السكربت، و$#عددها، و$?رمز خروج آخر أمر.if [ شرط ]; then ... fiمع-fو-dللملفات، و-eqو-gtللأرقام.for x in قائمة; do ... doneللتكرار على عناصر أو ملفات، وwhileما دام الشرط متحققاً.- مبروك! أنهيت كورس Linux: من أول أمر إلى سكربتات تؤدي عملك عنك.