پرسش و پاسخ شماره ۹۹ - آموزش اسکریپت نویسی
X
تبلیغات
رایتل

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

#!/bin/bash

پرسش و پاسخ شماره ۹۹

پرسش و پاسخ شماره ۹۹

چطور می‌توانم جدیدترین(یا قدیمی‌ترین) فایل یک شاخه را به دست آورم؟

این صفحه باید با پرسش و پاسخ شماره ۳ ادغام می‌شد.

پاسخ ‎ls -t | head -1‎ که فوراً به ذهن می‌رسد، اشتباه است، به علت آنکه تجزیه خروجی ls نا امن است، در عوض، باید حلقه‌ای ایجاد نموده و نشانه‌های زمان را مقایسه کنید:

# Bash
files=(*) newest=${files[0]}
for f in "${files[@]}"; do
  if [[ $f -nt $newest ]]; then
    newest=$f
  fi
done

آنوقت جدیدترین فایل(براساس زمان ویرایش فایل) را در ‎$newest‎ خواهید داشت. برای به دست آوردن قدیمی‌ترین فایل، به سادگی ‎-nt‎ را به ‎-ot‎ تغییر بدهید(برای لیستی از عملگرها ‎help test‎ را ببینید)، و البته برای اجتناب از تداخل، نام متغیرها را تغییر بدهید.

Bash وسیله‌ای غیر از mtime برای مقایسه نشانه‌های زمان فایل ندارد، بنابراین اگر بخواهید(برای مثال) آخرین فایل دستیابی شده (جدیدترین توسط atime) را به دست بیاورید، می‌باید از فرمان خارجی ‎stat(1)‎ (اگر آن را دارید) یا از فرمان finfo داخلی قابل بارگیری (اگر می‌توانید دستورات داخلی را بارگیری کنید) کمک بگیرید.

این هم مثالی از کاربرد stat از ‎coreutils 6.10‎ گنو (متأسفانه، حتی در میان سیستم‌های لینوکس، ترکیب دستوری فرمان stat سازگار نیست) برای به دست آوردن آخرین فایل دستیابی شده. ( در این نگارش، ‎%X‎ آخرین زمان دستیابی است.)

# Bash, GNU coreutils
newest= newest_t=0
for f in *; do
  t=$(stat --format=%X -- "$f")   # atime
  if ((t > newest_t)); then
    newest_t=$t
    newest=$f
  fi
done

این روش همچنین دارای اشکال تولید مثل یک برنامه خارجی برای هر فایل داخل دایرکتوری می‌باشد، پس، این روش فقط در صورت ضرورت باید به کار برود. برای به دست آوردن قدیمی‌ترین فایل با استفاده از این روش، یا باید ‎oldest_t‎ را با بیشترین مقدارِ ممکنِ نشانه زمان(گزاره مهارت‌آمیز، مخصوصاً چنانکه ما سال 2038 را پیشنهاد می‌کنیم)، یا با نشانه زمان اولین فایل در دایرکتوری، چنانکه در مثال اول دیدیم، مقداردهی کنید.

این هم یک راه‌حل دیگر با تولیدمثل یک برنامه خارجی، اما موافق با posix:

# posix
unset newest
for f in ./*; do
  # در اولین دور حلقه newest تنظیم متغیر‎
  newest=${newest-$f} 
  #  در find برای اجتناب از سیر نزولی در دایرکتوری‌ها می‌باشد، وضعیت خروج ‎-prune‎‎
  #  .اینجا بیفایده است، ما خروجی را بررسی می‌کنیم 
  if [ "$(find "$f" -prune -newer "$newest")" ]; then 
    newest=$f
  fi
done

مثال: چگونه غیر از آخرین دایرکتوری، همگی را حذف کنیم. (توجه، زمان ویرایش دایرکتوری زمان آخرین عملیاتی است که در آن دایرکتوری تغییر ایجاد می‌کند -- یعنی آخرین ایجاد، حذف، یا تغییرنام فایل در آن.)

 $ cat clean-old 
 dirs=(enginecrap/*/) newest=${dirs[0]}
 for d in "${dirs[@]}"
  do if [[ $d -nt $newest ]]
     then newest=$d
     fi
  done

 for z in "${dirs[@]}"
  do if [[ "$z" != "$newest" ]]
     then rm -rf "$z"
     fi
  done
 $ for x in 20101022 20101023 200101025 20101107 20101109; do mkdir enginecrap/"$x";done
 $ ls enginecrap/
 200101025       20101022        20101023        20101107        20101109
 $ ./clean-old 
 $ ls enginecrap/
 20101109


CategoryShell

پرسش و پاسخ 99 (آخرین ویرایش ‎2013-03-18 21:54:17‎ توسط geirha)