دستور داخلی read نقطه مقابل دستورات echo و printf میباشد. ترکیب دستور read به اینصورت است:
read
[options]
NAME1 NAME2 ... NAMEN
یک سطر از ورودی استاندارد یا توصیفگرفایل ارائه شده به عنوان شناسه با گزینه -u
را میخواند. اولین کلمه سطر ورودی به، NAME1
تخصیص داده میشود، دومین کلمه, بهNAME2
، و به همین ترتیب بقیه کلمات به نسبت فاصله خوردنهای جداکننده به بقیه اختصاص مییابند، تا آخرین نام، NAMEN
. اگر در جریان ورودی کلمات کمتری از نامها موجود باشد، به بقیه نامها مقدار تهی اختصاص مییابد.
کاراکترهای محتوای متغیر IFS
برای جدا کردن سطر ورودی به کلمات یا نشانهها به کار میرود، بخشی به نام«تفکیک کلمات» را ملاحظه کنید. ممکن است کاراکتر \ برای حذف معنی ویژه کاراکتر بعدی و ادامه سطر به کار رفته باشد.
اگر هیچ نامی برای دستور فراهم نشده باشد، محتوای متغیر REPLY
به عنوان سطر خوانده شده خواهد بود.
کد برگشتی فرمان read صفر است، مگر اینکه با یک کاراکتر انتهای فایل روبرو شود، یا زمان انتظار read سپری شود یا اگریک توصیفگرفایل نامعتبر به عنوان شناسه گزینه -u
فراهم شده باشد.
در Bash گزینههای زیر توسط فرمان داخلیread پشتیبانی میشوند:
جدول 8.2: گزینههای فرمان داخلی read
گزینه | معنی |
---|---|
-a ANAME | کلمات به ترتیب شاخصها به متغیر آرایهای ANAME اختصاص داده میشوند،با شروع از صفر. قبل از تخصیص تمام عناصر از ANAME حذف میشوند. سایر شناسههای NAME صرفنظر میشوند. |
-d DELIM | اولین کاراکتر از DELIM برای خاتمه دادن به سطر ورودی، زودتر از سطر جدید، استفاده میشود. |
-e | از readline برای گرفتن یک سطر استفاده میشود. |
-n NCHARS | read بعد از خواندن تعداد NCHARS کاراکتر قبل از آن که منتظر تکمیل سطر ورودی بماند، برمیگردد. |
-p PROMPT | قبل از خواندن ورودی یک PROMPT بدون انتقال به سطر بعدی نمایش میدهد. اعلان فقط در صورتیکه ورودی از یک ترمینال اخذ بشود نمایش داده خواهد شد. |
-r | اگر از این گزینه استفاده شود \ به عنوان یک کاراکتر گریز عمل نمیکند. ممیز برعکس به عنوان بخشی از سطر در نظر گرفته میشود. مخصوصاً ممیز برعکس و سطرجدید همراه هم میتوانند به عنوان ادامه سطر به کار بروند. |
-s | حالت خاموش. اگر ورودی از یک ترمینال گرفته میشود، کاراکترها نمایش داده نمیشوند. |
-t TIMEOUT | باعث میشود read توقف کرده و اگر طی زمان TIMEOUT ثانیه، سطر ورودی کاملی دریافت نکند، عدم موفقیت را برمیگرداند. این گزینه موقعی که read ورودیاش را از ترمینال یا از یک لوله نمیحواند، تأثیر ندارد. |
-u FD | ورودی را از توصیفگر فایل FD میخواند. |
این یک مثال سرراست، بهبود یافته اسکریپت leaptest.sh
فصل قبلی میباشد:
michel ~/test>
catleaptest.sh
#!/bin/bash # This script will test if you have given a leap year or not. echo "Type the year that you want to check (4 digits), followed by [ENTER]:" read year if (( ("$year" % 400) == "0" )) || (( ("$year" % 4 == "0") && ("$year" % 100 != "0") )); then echo "$year is a leap year." else echo "This is not a leap year." fimichel ~/test>
leaptest.sh Type the year that you want to check (4 digits), followed by [ENTER]: 2000 2000 is a leap year.
مثال زیر نشان میدهد که چطور میتوانید از اعلانها برای توضیح آن که کاربر چه چبز باید وارد کند، استفاده کنید.
michel ~/test>
catfriends.sh
#!/bin/bash # This is a program that keeps your address book up to date. friends="/var/tmp/michel/friends" echo "Hello, "$USER". This script will register you in Michel's friends database." echo -n "Enter your name and press [ENTER]: " read name echo -n "Enter your gender and press [ENTER]: " read -n 1 gender echo grep -i "$name" "$friends" if [ $? == 0 ]; then echo "You are already registered, quitting." exit 1 elif [ "$gender" == "m" ]; then echo "You are added to Michel's friends list." exit 1 else echo -n "How old are you? " read age if [ $age -lt 25 ]; then echo -n "Which colour of hair do you have? " read colour echo "$name $age $colour" >> "$friends" echo "You are added to Michel's friends list. Thank you so much!" else echo "You are added to Michel's friends list." exit 1 fi fimichel ~/test>
cpfriends.sh /var/tmp
; cd/var/tmp
michel ~/test>
touchfriends
; chmoda+w
friends
michel ~/test>
friends.sh Hello, michel. This script will register you in Michel's friends database. Enter your name and press [ENTER]: michel Enter your gender and press [ENTER] :m You are added to Michel's friends list.michel ~/test>
catfriends
توجه کنید که در اینجا هیچ خروجی حذف نگردیده است. اسکریپت فقط اطلاعات در باره اشخاص مورد علاقه Michel را نگهداری میکند، فقط همواره به شما میگوید که به لیست اضافه شدهاید، مگر آنکه از قبل در لیست باشید.
حالا سایر کاربران میتوانند اسکریپت را اجرا کنند:
[anny@octarine tmp]$
friends.sh
Hello, anny. This script will register you in Michel's friends database.
Enter your name and press [ENTER]: anny
Enter your gender and press [ENTER] :f
How old are you? 22
Which colour of hair do you have? black
You are added to Michel's friends list.
پس از یک دوره، لیست friends
به این شکل میشود:
tille 24 black anny 22 black katya 22 blonde maria 21 black --output omitted--
البته، این وضعیت مطلوبی نیست، چون هر شخصی میتواند فایلهای Michel را ویرایش کند( اما حذف خیر). شما میتوانید این مشکل را با استفاده از وضعیتهای دسترسی ویژه در اسکریپت رفع نمایید، به بخش SUID and SGID در مقدمه راهنمای لینوکس نگاه کنید.
به طوری که از بخش مبانی پوسته میدانید، ورودی و خروجی یک دستور ممکن است قبل از اینکه اجرا گردد، با استفاده از یک نشانهگذاری ویژه -عملگرهای تغییر مسیر- قابل تفسیر توسط پوسته، تغییر مسیر داده شوند. همینطور هم، تغییر مسیر ممکن است جهت باز کردن و بستن فایلها برای محیط اجرایی پوسته جاری استفاده شود.
همچنین تغییر مسیر میتواند در یک اسکریپت رخ بدهد، به طوری که میتواند ورودی را به عنوان مثال، از یک فایل دریافت نماید ، یاخروجی را به یک فایل ارسال کند. بعداً، کاربر میتواند فایل خروجی را بازبینی کند، یابه عنوان ورودی اسکریپت دیگری استفاده شود.
فایل ورودی و خروجی با دستگیره های( handles ) صحیحی همراه شدهاند که همه فایلهای باز یک پردازش را پیگردی میکنند. این کمیتهای عددی( دستگیرهها) به عنوان توصیفگرهای فایل شناخته شدهاند. شناخته شدهترین توصیفگرها stdin, stdout, stderr به ترتیب با شمارههای 2, 1, 0 میباشند. این اعداد و دستگاههای مربوطه رزرو شده هستند. Bash میتواند به خوبی با درگاههای TCP یا UDPمیزبانهای شبکهای به عنوان یک توصیفگر فایل عمل کند.
خروجی پایین نشان میدهد که چگونه توصیفگرهای فایل رزرو شده به دستگاههای واقعی اشاره میکنند:
michel ~>
ls-l
/dev/std*
lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stderr -> ../proc/self/fd/2 lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stdin -> ../proc/self/fd/0 lrwxrwxrwx 1 root root 17 Oct 2 07:46 /dev/stdout -> ../proc/self/fd/1michel ~>
ls-l
/proc/self/fd/[0-2]
lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/0 -> /dev/pts/6 lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/1 -> /dev/pts/6 lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/2 -> /dev/pts/6
توجه نمایید که هر پردازش نگاه خاص خود را به فایلهای تحت دایرکتوری /proc/self
دارد، چون در واقع یک پیوند نمادین به /proc/<process_ID>
میباشد.
میتوانید info MAKEDEV و info proc را برای اطلاعات بیشتر در باره دایرکتوریهای زیرمجموعه /proc
و روشی که سیستم شما توصیفگرهای فایل استاندارد برای هر پردازش در حال اجرا را مدیریت میکند، ببینید.
وقتی یک فرمان صادره دارد اجرا میشود، مراحل زیر به ترتیب اجرا میگردند:
اگر خروجی استاندارد دستور قبلی به ورودی استاندارددستور فعلی لولهکشی شده باشد، آنوقت:
/proc/<current_process_ID>/fd/0
به مقصد همان لوله ناشناس به صورت /proc/<previous_process_ID/fd/1
به هنگامسازی میشود.اگر خروجی استاندارد دستور فعلی به ورودی استاندارد دستور بعدی لولهکشی شده باشد، آنوقت:
/proc/<current_process_ID>/fd/1
به مقصد یک لوله ناشناس دیگر به هنگامسازی میشود.تغییر مسیر برای دستور فعلی از چپ به راست انجام میشود.
تغییر مسیر “N>&M” یا “N<&M” بعد از یک فرمان، تأثیر ایجاد یا به هنگامسازی پیوند نمادین
/proc/self/fd/N
با مقصد همان پیوند نمادین /proc/self/fd/M
را دارد.تغییر مسیرهای “N> file” و “N< file” نتیجه ایجاد یا به هنگامسازی پیوند نمادین
/proc/self/fd/N
به فایل مقصد را دارند.بسته شدن توصیفگر فایل “N>&-” اثر حذف پیوند نمادین
/proc/self/fd/N
را دارد.اکنون فقط فرمان اجرا شده است .
موقعی که اسکریپت را از خطفرمان اجرا میکنید، چیز مهمی تغییر نمیکند، چون پردازش پوسته فرزند از همان توصیفگر فایل والد استفاده میکند. وقتی که چنین والدی در دسترس نباشد، به عنوان نمونه موقعی که اسکریپت را با استفاده از امکان cron اجرا میکنید، توصیفگرهای استاندارد فایل، لولهها یا سایر فایلها(موقتی) هستند، مگر اینکه برخی تغییر مسیرها به کار رفته باشند. این موارد در مثال زیر، که خروجی یک اسکریپت ساده at را نشان میدهد، به نمایش درآمدهاند:
michel ~>
date Fri Jan 24 11:05:50 CET 2003michel ~>
at1107
warning: commands will be executed using (in order) a) $SHELL b) login shell c)/bin/shat>
ls-l
/proc/self/fd/
>/var/tmp/fdtest.at
at>
<EOT> job 10 at 2003-01-24 11:07michel ~>
cat/var/tmp/fdtest.at
total 0 lr-x------ 1 michel michel 64 Jan 24 11:07 0 -> /var/spool/at/!0000c010959eb (deleted) l-wx------ 1 michel michel 64 Jan 24 11:07 1 -> /var/tmp/fdtest.at l-wx------ 1 michel michel 64 Jan 24 11:07 2 -> /var/spool/at/spool/a0000c010959eb lr-x------ 1 michel michel 64 Jan 24 11:07 3 -> /proc/21949/fd
و این مثال با cron:
michel ~>
crontab-l
# DO NOT EDIT THIS FILE - edit the master and reinstall. # (/tmp/crontab.21968 installed on Fri Jan 24 11:30:41 2003) # (Cron version -- $Id: chap8.xml,v 1.9 2006/09/28 09:42:45 tille Exp $) 32 11 * * * ls -l /proc/self/fd/ > /var/tmp/fdtest.cronmichel ~>
cat/var/tmp/fdtest.cron
total 0 lr-x------ 1 michel michel 64 Jan 24 11:32 0 -> pipe:[124440] l-wx------ 1 michel michel 64 Jan 24 11:32 1 -> /var/tmp/fdtest.cron l-wx------ 1 michel michel 64 Jan 24 11:32 2 -> pipe:[124441] lr-x------ 1 michel michel 64 Jan 24 11:32 3 -> /proc/21974/fd
از مثال قبلی آشکار است، که میتوانید فایلهای ورودی و حروجی برای اسکریپت فراهم کنید( برای مطالب بیشتر بخشی به نام« فایل ورودی و خروجی » را ببینید )، اما قدری مراقب فراموشی تغییر مسیر خطاها باشید - خروجی که میتواند موکول به بعد باشد. همچنین اگر خوش شانس باشید، خطاها برای شما ایمیل میشود و دلایل احتمالی خرابی میتواند آشکار گردد. خوش شانس نباشید، خطاها موجب واماندگی اسکریپت شما میشود و دریافت یا به جایی ارسال نمیگردند، به طوریکه نمیتوانید اشکالزدایی ارزندهای را شروع کنید.
موقع تغییر مسیر خطاها، ترتیب تقدم با اهمیت میباشد. به عنوان مثال، این فرمان، که در /var/spool
صادر گردیده
ls -l
*
2
> /var/tmp/unaccessible-in-spool
خروجی استاندارد فرمان ls را به فایل unaccessible-in-spool
در دایرکتوری /var/tmp
تغییر مسیر خواهد داد. دستور
ls -l
*
> /var/tmp/spoollist
2
>&1
هر دوی ورودی استاندارد و خروجی استاندارد خطا را به فایلspoollist
هدایت خواهد نمود. دستور
ls -l
*
2
>& 1
> /var/tmp/spoollist
فقط خروجی استاندارد را به فایل مقصد هدایت میکند، به دلیل آنکه خروجی استاندارد خطا قبل از اینکه خروجی استاندارد تغییر مسیر داده شود، به آن کپی گردیده است.
اغلب برای راحتی، خطاها، در صورت اطمینان به عذم نیاز به آنها، به دستگاه /dev/null
تغییر مسیر داده میشوند. صدها مثال در اسکریپتهای شروع اولیه سیستم شما یافت میشود.
Bash اجازه میدهدخروجی استاندارد و خرجی استاندارد خطا به فایلی که نامش نتیجه بسط FILE
با این ساختار:
&>
FILE
میباشد تغییر مسیر داده شود. این معادل > FILE
2>&1 میباشد، ساختاری که در مجموعه مثالهای قبلی به کار رفته است. همچنین اغلب با تغییر مسیر به /dev/null
ترکیب میشود، به عنوان نمونه وقتی شما میخواهید فقط یک دستور اجرا شود، و مهم نیست چه خروجی یا خطایی میدهد .
دایرکتوری /dev/fd
شامل ورودیهایی به نام 0
, 1
, 2
,و غیره میباشد. باز کردن فایل /dev/fd/N
معادل دونسخهای کردن توصیفگر فایل N میباشد. اگر سیستم شما /dev/stdin
و /dev/stdout
و /dev/stderr
را تأمین کند، خواهید دید که اینها به ترتیب معادل /dev/fd/0
و /dev/fd/1
و /dev/fd/2
، هستند.
استفاده اصلی از فایلهای /dev/fd
بواسطه پوسته است. این مکانیسم به برنامهها اجازه میدهد که ازشناسههای نام مسیر ورودی و خروجی استاندارد به همان روش سایر نام مسیرها استفاده کنند. اگر /dev/fd
روی سیستم در دسترس نباشد، شما باید راهی برای رفع مشکل پیدا کنید. این کار به عنوان مثال میتواند با کاربرد خطتیره (-) برای نشان دادن آنکه برنامه باید از یک لوله بخواند، مرتفع گردد. یک مثال:
michel ~>
filterbody.txt.gz
| catheader.txt
-footer.txt
This text is printed at the beginning of each print job and thanks the sysadmin for setting us up such a great printing infrastructure. Text to be filtered. This text is printed at the end of each print job.
دستور cat اول فایل header.txt
را میخواند، بعد ورودی استانداردش را که خروجی استاندارد فرمان filter است، و در آخر فایلfooter.txt
. معنی خاص خطتیره به عنوان یک شناسه خطفرمان برای ارجاع به ورودی یا خروجی استاندارد یک تصور غلط است که در بسیاری از برنامهها crept دارد. همچنین موقعی که خطتیره به عنوان اولین شناسه تعیین میشود، میتواند مشکلاتی به وجود آورد، چون میتواند به عنوان یک گزینه مقدم بر فرمان تفسیر گردد. کاربرد /dev/fd
یکنواختی و پیشگیری از درهموبرهمی را میسر میکند:
michel ~>
filterbody.txt
| catheader.txt /dev/fd/0 footer.txt
| lp
در این مثال پاکیزه، تمام خروجی به طور اضافه شدنی از میان lp برای ارسال به چاپگر پیشفرض لولهکشی شدهاند.
نگاه دیگری به توصیفگرهای فایل، در نظر گرفتن آنها به عنوان روش اختصاص یک مقدار عددی به یک فایل است. به جای استفاده از نام یک فایل، میتوانید شماره توصیفگرفایل را به کار ببرید. فرمان داخلی exec میتواند برای جایگزینی پردازش پوسته جاری یا برای تغییر دادن توصیفگرهایفایل پوسته جاری به کار رود. به عنوان مثال، میتواند برای اختصاص یک توصیفگر به یک فایل استفاده شود. دستور
exec fdN>
را برای اختصاص توصیفگرفایل N به file
file
برای خروجی، وexec fdN<
را برای اختصاص توصیفگرفایل N به file
file
برای ورودی، به کار ببرید.
پس از اینکه یک توصیفگرفایل به فایلی اختصاص داده شد، میتواند با عملگرهای تغییر مسیر پوسته به طوری که در مثال زیر نمایش داده شده است، استفاده شود:
michel ~>
exec4
>result.txt
michel ~>
filterbody.txt
| catheader.txt /dev/fd/0 footer.txt
>&4
michel ~>
catresult.txt
This text is printed at the beginning of each print job and thanks the sysadmin for setting us up such a great printing infrastructure. Text to be filtered. This text is printed at the end of each print job.
توصیفگرفایل 5 | |
---|---|
استفاده از این توصیفگر ممکن است باعث بروز مشکلاتی گردد، به راهنمای پیشرفته اسکریپت نویسی Bash, فصل 16 نگاه کنید. قویاً به شما توصیه میشود از این توصیفگر استفاده نکنید. |
مثال زیر به شما نشان میدهد که چگونه میتوانید بین ورودی از فایل و ورودی از خطفرمان تغییر وضعیت بدهید:
michel ~/testdir>
catsysnotes.sh
#!/bin/bash # This script makes an index of important config files, puts them together in # a backup file and allows for adding comment for each file. CONFIG=/var/tmp/sysconfig.out rm "$CONFIG" 2>/dev/null echo "Output will be saved in $CONFIG." # create fd 7 with same target as fd 0 (save stdin "value") exec 7<&0 # update fd 0 to target file /etc/passwd exec < /etc/passwd # Read the first line of /etc/passwd read rootpasswd echo "Saving root account info..." echo "Your root account info:" >> "$CONFIG" echo $rootpasswd >> "$CONFIG" # update fd 0 to target fd 7 target (old fd 0 target); delete fd 7 exec 0<&7 7<&- echo -n "Enter comment or [ENTER] for no comment: " read comment; echo $comment >> "$CONFIG" echo "Saving hosts information..." # first prepare a hosts file not containing any comments TEMP="/var/tmp/hosts.tmp" cat /etc/hosts | grep -v "^#" > "$TEMP" exec 7<&0 exec < "$TEMP" read ip1 name1 alias1 read ip2 name2 alias2 echo "Your local host configuration:" >> "$CONFIG" echo "$ip1 $name1 $alias1" >> "$CONFIG" echo "$ip2 $name2 $alias2" >> "$CONFIG" exec 0<&7 7<&- echo -n "Enter comment or [ENTER] for no comment: " read comment; echo $comment >> "$CONFIG" rm "$TEMP"michel ~/testdir>
sysnotes.sh Output will be saved in /var/tmp/sysconfig.out. Saving root account info... Enter comment or [ENTER] for no comment: hint for password: blue lagoon Saving hosts information... Enter comment or [ENTER] for no comment: in central DNSmichel ~/testdir>
cat/var/tmp/sysconfig.out
Your root account info: root:x:0:0:root:/root:/bin/bash hint for password: blue lagoon Your local host configuration: 127.0.0.1 localhost.localdomain localhost 192.168.42.1 tintagel.kingarthur.com tintagel in central DNS
نظر به اینکه پردازشهای فرزند از توصیفگرفایلهای باز ارث میبرند، بستن یک توصیفگرفایل موقعی که نیازی به آن نیست تمرین خوبی است. این کار با ترکیب دستوری زیر انجام میشود.
exec fd<&-
در مثال فوق، توصیفگرفایل شماره 7، که به ورودی استاندارد تخصیص یافته است، هر دفعه که دسترسی به ورودی استاندارد واقعی، که به طور معمول صفحه کلید است، موردنیاز کاربر است، بسته میشود.
مثال ساده زیر فقط خروجی استاندارد خطا را به یک لوله تغییر مسیر میدهد:
michel ~>
catlistdirs.sh
#!/bin/bash # This script prints standard output unchanged, while standard error is # redirected for processing by awk. INPUTDIR="$1" # fd 6 targets fd 1 target (console out) in current shell exec 6>&1 # fd 1 targets pipe, fd 2 targets fd 1 target (pipe), # fd 1 targets fd 6 target (console out), fd 6 closed, execute ls ls "$INPUTDIR"/* 2>&1 >&6 6>&- \ # Closes fd 6 for awk, but not for ls. | awk 'BEGIN { FS=":" } { print "YOU HAVE NO ACCESS TO" $2 }' 6>&- # fd 6 closed for current shell exec 6>&-
امکان دارد اسکریپت شما بارها در برنامه یا اسکریپت دیگری فراخوانی بشود. here document( سند اینجا ) روشی برای راهنمایی پوسته فراهم میکند، که ورودی را ازمنبع جاری تا رسیدن به سطری که فقط شامل یک رشته جستجو( بدون بهدنبال کشیدن فاصلهها ) است، بخواند. بعد تمام سطرهای خوانده شده تا آن نقطه، به عنوان ورودی استاندارد یک فرمان هستند .
نتیجه آنکه، نیازی نیست فایلهای جداگانهای فراخوانی کنید، از کاراکترهای ویژه پوسته میتوانید استفاده کنید، و زیباتر از یک گروه دستورecho میباشد:
michel ~>
catstartsurf.sh
#!/bin/bash # This script provides an easy way for users to choose between browsers. echo "These are the web browsers on this system:" # Start here document cat << BROWSERS mozilla links lynx konqueror opera netscape BROWSERS # End here document echo -n "Which is your favorite? " read browser echo "Starting $browser, please wait..." $browser &michel ~>
startsurf.sh These are the web browsers on this system: mozilla links lynx konqueror opera netscapeWhich is your favorite?
opera Starting opera, please wait...
با اینکه ما در باره یک here document صحبت میکنیم، فرض شده است که یک ساختار در همان اسکریپت باشد. این یک مثال است که یک بسته را به طور خودکار نصب میکند، ولواینکه به طور معمول شما باید تأیید کنید:
#!/bin/bash # This script installs packages automatically, using yum. if [ $# -lt 1 ]; then echo "Usage: $0 package." exit 1 fi yum install $1 << CONFIRM y CONFIRM
و چگونگی اجرای آن این است. موقعیکه جمله “Is this ok [y/N]”نمایش داده میشود، اسکریپت به طور خودکار پاسخ “y” میدهد:
[root@picon bin]#
./install.shtuxracer
Gathering header information file(s) from server(s) Server: Fedora Linux 2 - i386 - core Server: Fedora Linux 2 - i386 - freshrpms Server: JPackage 1.5 for Fedora Core 2 Server: JPackage 1.5, generic Server: Fedora Linux 2 - i386 - updates Finding updated packages Downloading needed headers Resolving dependencies Dependencies resolved I will do the following: [install: tuxracer 0.61-26.i386]Is this ok [y/N]:
EnterDownloading Packages Running test transaction: Test transaction complete, Success! tuxracer 100 % done 1/1 Installed: tuxracer 0.61-26.i386 Transaction(s) Complete