program_list
آیا هیچ از آن همه فایلهای داخل /usr/bin تعجب کردهاید؟ البته که تعجب کردهاید! بسیار خوب، شما میتوانستید یک whatis روی هر فایل در دایرکتوری(که در یک سیستم معمولی تعداد آنها میتواند یکهزار یا بیشتر باشد) انجام بدهید، یا میتوانید اسکریپت زیر را اجرا کنید.
program_list برنامهای است که یک لیست تفسیری از برنامههای یک دایرکتوری(پیشفرض آن /usr/bin است) با نمایش شرح هر برنامه تولید میکند. همچنین، نام بستهای را که برنامه به آن تعلق دارد نیز لیست میکند، یک سرنخِ مفید دیگر برای تعیین آنچه برنامه انجام میدهد.
برنامه خروجیاش را در سه قالب متفاوت به خروجی استاندارد ارسال میکند، متن ساده(پیشفرض)، کمیتهای جداشده با tab (عالی برای پردازش بعدی لیست با سایر ابزارها یا بارگذاری آن داخل یک صفحهگسترده)، و قالب Markdown برای تبدیل مستقیم به HTML و سایر قالبها.
program_list باید در هر سیستم بر مبنای rpm (از قبیل Red Hat، CentOS، Fedora، وغیره) یا بر پایه deb (مانند Debian، Ubuntu، و غیره) کار کند. به هر حال توجه داشته باشید که به سبب سرعت پایین جستجوی بسته روی اکثر سیستمها، اجرای program_list میتواند زمان زیادی(تا نیم ساعت یا بیشتر) نسبت به سرعت سیستم شما و تعداد فایلهای موجود، صرف کند.
علاوه بر دایرکتوری پیشفرض /usr/bin، برای دایرکتوری /bin، /sbin، و /usr/sbin نیز مناسب است.
مثالها
me@linuxbox ~ $ program_list > program_list.txt
یک لیست متن ساده از /usr/bin تولید میکند و آن را در فایلی به نام program_list.txt
ذخیره میکند.
me@linuxbox ~ $ program_list -t /usr/sbin > program_list_usr_sbin.tsv
یک لیست با کمیت جدا شده با tab از /usr/sbin تولید و آن را در فایلی به نام program_list_usr_sbin.tsv
ذخیره میکند.
#!/bin/bash
# ---------------------------------------------------------------------------
# program_list - تولید یک لیست تفسیری از برنامهها
# Copyright 2014, William Shotts <bshotts@users.sourceforge.net>
# این برنامه نرمافزار آزاد است: شما میتوانید آن را تحت شرایط نگارش
# گنو یا به انتخاب خودتان هر نگارش پس از آن که GPL شماره 3 مجوز
# .توسط بنیاد نرمافزارهای آزاد اعلام گردیده، توزیع و یا ویرایش کنید
# این برنامه به امید آنکه سودمند باشد توزیع میگردد، اما بدون هرگونه
# تعهد حتی تعهد ضمنی کیفیت یا صلاحیت برای یک مقصود خاص. برای جزییات
# .ببینید (http://www.gnu.org/licenses/) گنو را در GPL بیشتر مجوز
# /usr/bin این برنامه یک لیست تفسیری از برنامههای دایرکتوری
# (یا دایرکتوری تعیین شده کاربر) شامل نام فایل، نام بستهای
# man که بواسطه آن نصب شده است و شرح مختصر اخذ شده از صفحه
# برنامه اگر در دسترس باشد، تولید میکند. قالب لیست میتواند
# (مفید برای tab متن ساده(قالب پیشفرض)، کمیتهای جدا شده با
# .باشد Markdown وارد کردن لیست به سایر برنامهها)، یا قالب
# program_list [-h|--help] : نحوه کاربرد
# program_list [[-m|--markdown]|[-t|--tabs]] [directory]
# :تاریخچه بازبینی
# 2014-01-27 در برابر نامهای ناخوشایند تقویت گردید (ver. 1.1)
# 2014-01-17 ایجاد گردید new_script اسکریپت 3.0.1 به وسیله نگارش
# ---------------------------------------------------------------------------
PROGNAME=${0##*/}
VERSION="1.1"
clean_up() { # انجام خانهتکانی قبل از خروج
return
}
error_exit() { # مدیریت خطاهای مهلک
echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2
clean_up
exit 1
}
graceful_exit() {
clean_up
exit
}
signal_exit() { # شده trap اداره سیگنالهای
case $1 in
INT)
error_exit "Program interrupted by user" ;;
TERM)
echo -e "\n$PROGNAME: Program terminated" >&2
graceful_exit ;;
*)
error_exit "$PROGNAME: Terminating on unknown signal" ;;
esac
}
usage() {
echo -e "Usage: $PROGNAME [-h|--help]|[[-m|-t] [directory]]"
}
help_message() {
cat <<- _EOF_
$PROGNAME ver. $VERSION
Produce an annotated listing of programs in a directory
$(usage)
Options:
-h, --help Display this help message and exit.
-m, --markdown Output Markdown formatted text (with pandoc
extensions).
-t, --tabs Output tab-separated values.
directory is optional. Default is /usr/bin.
_EOF_
return
}
set_mode() { # تنظیم قالب خروجی
if [[ $mode == "empty" ]]; then
mode=$1
else
error_exit "Only one mode (-m or -t) is allowed."
fi
}
string() { # مرتبه تکرار شده "width" که "char" نوشتن یک رشته کاراکتر
local -i width="$1"
local char="$2"
head -c "$width" < /dev/zero | tr '\0' "$char"
}
find_package() { # جستجو برای نام بسته بر مبنای توزیع
local filename="$1" raw_package
case $distro_style in
debian)
raw_package="$(dpkg-query -S "$filename" 2> /dev/null | tail -1)"
echo "${raw_package%:*}"
;;
redhat)
rpm -qf "$filename" 2> /dev/null
;;
*)
error_exit "Unsupported distribution."
;;
esac
}
# Trap سیگنالهای
trap "signal_exit TERM" TERM HUP
trap "signal_exit INT" INT
# تجزیه سطرفرمان
mode=empty
program_directory=/usr/bin
while [[ -n "$1" ]]; do
case "$1" in
-h | --help)
help_message
graceful_exit
;;
-m | --markdown)
set_mode markdown
;;
-t | --tabs)
set_mode tsv
;;
-* | --*)
usage
error_exit "Unknown option $1"
;;
*)
program_directory="$1"
break
;;
esac
shift
done
# منطق اصلی
declare -a filenames packages descriptions
declare -i index=1 max_fn_len=0 fn_len=0 col1_width col2_width
distro_style="unknown"
# تعیین نوع سیستم بستهبندی
[[ -x /usr/bin/apt-get ]] && distro_style="debian"
[[ -x /bin/rpm || -x /usr/bin/rpm ]] && distro_style="redhat"
# معتبر است program_directory بررسی آنکه
[[ -d "$program_directory" ]] || \
error_exit "$program_directory cannot be read"
# بار گیری آرایه با نام فایلها، بستهها، و توضیحها
while IFS= read -r i; do
filenames[index]="${i##*/}"
fn_len=${#filenames[index]}
# تعیین طولانیترین نامفایل برای محاسبه عرض ستون
[[ $fn_len -gt $max_fn_len ]] && max_fn_len=$fn_len
packages[index]="$(find_package "$i")"
# گرفتن توضیح برنامه، دور ریختن ابتدای آن و
# .بزرگ کردن حرف ابتدای اولین کلمه
raw_description="$(whatis "${filenames[index]}" 2>/dev/null | head -1)"
raw_description="${raw_description##*' - '}"
descriptions[index]="${raw_description^*}"
((++index))
done < <(find "$program_directory" -mindepth 1 -maxdepth 1 -executable \
-not -type d | sort -u)
# Markdown درج سرآیند
if [[ $mode == "markdown" ]]; then
markdown_header="Programs in $program_directory"
echo -e "$markdown_header\n$(string ${#markdown_header} "=")\n\n"
((max_fn_len += 4)) # اجازه برای افزودن کاراکترهای اضافی به نام فایلها
fi
# محاسبه عرض ستونها
col1_width=$((max_fn_len + 1))
col2_width=$((80 - col1_width))
# Markdown درج جدول
if [[ $mode == "markdown" ]]; then
echo "$(string $max_fn_len '-') $(string $col2_width '-')"
fi
for ((i=1; i<index; ++i)); do
case $mode in
empty)
printf "%-${max_fn_len}s Package:%s\n" \
"${filenames[i]}" \
"${packages[i]}"
# اندازه کردن توضیح برای ستون دوم
echo "${descriptions[i]}" | \
fold -s -w $col2_width | \
pr -T -o $col1_width
echo
;;
tsv)
printf "%s\t%s\t%s\n" \
"${filenames[i]}" \
"${packages[i]}" \
"${descriptions[i]}"
;;
markdown)
printf "%-${max_fn_len}s Package:%s\n\n" \
"**${filenames[i]}**" \
"${packages[i]}"
echo "${descriptions[i]}" | \
fold -s -w $col2_width | \
pr -T -o $col1_width
echo
;;
esac
done
# Markdown بستن جدول
[[ $mode == "markdown" ]] && echo -e "$(string 80 '-')\n"
graceful_exit
|