رفتن به محتوا
LoopX

آزمون بخش ۱: مبانی

این آزمون شش درس بخش «مبانی» را می‌سنجد. جواب هر سؤال همان لحظه با توضیح نشان داده می‌شود و نتیجه‌ات در همین مرورگر ذخیره می‌شود (پیشرفت من).

؟ آزمون بخش ۱
  1. خط #!/usr/bin/env bash در اول اسکریپت چه می‌کند؟

  2. اسکریپتی بدون مجوز اجرا را با کدام دستور اجرا می‌کنی؟

  3. اسکریپتی از ویندوز آمده و ./script.sh خطای ‘bash\r’: No such file or directory می‌دهد. علت؟

  4. اسکریپتی دستور cd /tmp دارد. بعد از ./script.sh پوشه‌ی ترمینال تو چه می‌شود؟

  5. کد خروج اسکریپتی که دستور وسطش خطا داده ولی دستور آخرش echo done است چیست؟

  6. کدام انتساب در Bash درست است؟

  7. file="my report.txt" و دستور rm $file چه می‌کند؟

  8. name="report" و echo "$name_final" چه چاپ می‌کند؟

  9. echo $((7 / 2)) چه چاپ می‌کند و چرا؟

  10. month=08 و echo $((month + 1)) چه می‌شود؟

  11. برای ساخت اسم backup-2026-10-04.tar.gz با تاریخ امروز کدام درست است؟

  12. در ./backup.sh /data "my dir" مقدار $# چند است؟

  13. برای پاس‌دادن همه‌ی آرگومان‌ها به یک دستور دیگر، بدون خراب‌شدن آرگومان‌های دارای فاصله، چه می‌نویسی؟

  14. echo "Ali 30" | read name age و بعد echo $name چه می‌دهد؟

  15. چرا رمز را نباید به‌صورت آرگومان به اسکریپت داد؟

  16. در Bash، if دقیقاً چه چیزی را می‌سنجد؟

  17. نتیجه‌ی [[ 9 > 10 ]] چیست؟

  18. در [[ 1 -eq 1 ]] && false || echo "C" آیا C چاپ می‌شود؟

  19. if grep -q root /nonexistent; then ... else ... fi وقتی فایل وجود ندارد کدام شاخه را اجرا می‌کند؟

  20. در case، شاخه‌ی *) را کجا می‌گذاری و چرا؟

  21. الگوهای case از چه نوع‌اند؟

  22. for f in *.jpg وقتی هیچ jpg ای در پوشه نیست چه می‌شود؟

  23. چرا for i in {1..$n} کار نمی‌کند؟

  24. کدام الگو یک فایل را خط‌به‌خط و بدون دست‌کاری فاصله‌ها و بک‌اسلش‌ها می‌خواند؟

🏁 چالش: جعبه‌ابزار مدیر سیستمسخت

با همه‌ی آنچه در این بخش آموختی، اسکریپت toolbox.sh را بنویس؛ ابزاری با سه زیردستور:

۱. ./toolbox.sh count <پوشه>: تعداد فایل‌های معمولی پوشه را چاپ کند (فقط خود پوشه، نه زیرپوشه‌ها). اگر آرگومان نبود، پیام راهنما روی stderr و کد خروج ۱؛ اگر پوشه وجود نداشت، پیام خطا و کد خروج ۲. ۲. ./toolbox.sh stamp <پوشه>: هر فایل .txt آن پوشه را با پیشوند تاریخ امروز تغییر نام بدهد (a.txt ← 2026-10-04-a.txt)؛ نام‌های دارای فاصله هم کار کنند، فایلی که قبلاً پیشوند تاریخ دارد دست نخورد، روی فایل موجود رونویسی نشود، و در پایان تعداد تغییر نام‌ها را چاپ کند. ۳. ./toolbox.sh disk [آستانه]: اگر درصد پر بودن / از آستانه (پیش‌فرض ۸۰) بیشتر بود، WARNING چاپ کند و با کد ۱ تمام شود، وگرنه OK و کد ۰. آستانه‌ی غیرعددی ← خطا و کد ۲. ۴. هر زیردستور ناشناخته (یا بدون زیردستور): راهنما روی stderr و کد خروج ۱. ۵. ثابت کن همه‌ی مسیرها (موفق و خطا) را اجرا کرده‌ای و کد خروج هر کدام همان است که گفتیم. ۶. همه‌چیز را پاک کن.

راهنمایی

ساختار: command="$1"; shift; case "$command" in count) ... ;; stamp) ... ;; disk) ... ;; *) ... ;; esac. برای count: find "$1" -maxdepth 1 -type f | wc -l. برای stamp: shopt -s nullglob، for f in *.txt، الگوی [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-* در یک case داخلی و mv -- "$f" "$today-$f". برای disk: df --output=pcent / | tail -n 1 | tr -dc '0-9' و اعتبارسنجی با [[ $threshold =~ ^[0-9]+$ ]].

راه‌حل
mkdir -p ~/bashlab/quiz1 && cd ~/bashlab/quiz1
cat > toolbox.sh <<'EOF'
#!/usr/bin/env bash
# toolbox.sh: a tiny sysadmin toolbox
# Usage: ./toolbox.sh count <dir> | stamp <dir> | disk [threshold]
command="$1"
shift
case "$command" in
count)
if [[ $# -ne 1 ]]; then
echo "Usage: $0 count <dir>" >&2
exit 1
fi
if [[ ! -d $1 ]]; then
echo "Error: '$1' is not a directory" >&2
exit 2
fi
total=$(find "$1" -maxdepth 1 -type f | wc -l)
echo "$1 has $total files"
;;
stamp)
if [[ $# -ne 1 || ! -d $1 ]]; then
echo "Usage: $0 stamp <dir>" >&2
exit 1
fi
cd "$1" || exit 1
today=$(date +%F)
renamed=0
shopt -s nullglob
for f in *.txt; do
case "$f" in
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-*) continue ;;
esac
if [[ -e "$today-$f" ]]; then
echo "skip (target exists): $f"
continue
fi
mv -- "$f" "$today-$f"
((renamed++))
done
echo "renamed $renamed files"
;;
disk)
threshold="${1:-80}"
if [[ ! $threshold =~ ^[0-9]+$ ]]; then
echo "Error: threshold must be a number" >&2
exit 2
fi
usage=$(df --output=pcent / | tail -n 1 | tr -dc '0-9')
if (( usage > threshold )); then
echo "WARNING: / is ${usage}% full (limit ${threshold}%)"
exit 1
fi
echo "OK: / is ${usage}% full (limit ${threshold}%)"
;;
*)
echo "Usage: $0 count <dir> | stamp <dir> | disk [threshold]" >&2
exit 1
;;
esac
EOF
chmod +x toolbox.sh
mkdir -p docs && touch docs/a.txt "docs/my notes.txt" docs/b.md docs/2026-01-01-old.txt
echo "== count"
./toolbox.sh count docs; echo "کد: $?"
./toolbox.sh count; echo "کد: $?"
./toolbox.sh count nowhere; echo "کد: $?"
echo "== stamp"
./toolbox.sh stamp docs; echo "کد: $?"
ls docs
./toolbox.sh stamp docs; echo "کد: $?"
echo "== disk"
./toolbox.sh disk; echo "کد: $?"
./toolbox.sh disk 3; echo "کد: $?"
./toolbox.sh disk abc; echo "کد: $?"
echo "== unknown"
./toolbox.sh frobnicate; echo "کد: $?"
./toolbox.sh; echo "کد: $?"
echo "== پاک‌سازی"
cd ~ && rm -rf ~/bashlab
خروجی
== count
docs has 4 files
کد: 0
Usage: ./toolbox.sh count <dir>
کد: 1
Error: 'nowhere' is not a directory
کد: 2
== stamp
renamed 2 files
کد: 0
2026-01-01-old.txt
2026-10-04-a.txt
2026-10-04-my notes.txt
b.md
renamed 0 files
کد: 0
== disk
OK: / is 6% full (limit 80%)
کد: 0
WARNING: / is 6% full (limit 3%)
کد: 1
Error: threshold must be a number
کد: 2
== unknown
Usage: ./toolbox.sh count <dir> | stamp <dir> | disk [threshold]
کد: 1
Usage: ./toolbox.sh count <dir> | stamp <dir> | disk [threshold]
کد: 1
== پاک‌سازی