Emmanual Rouat مثال پایین را در مورد تجزیه و تبدیل نام فایلها و بویژه، نام مسیرها، اهدا نموده است. این مثال به استفاده زیاد از تواناییهای sed نزدیک میشود.
#!/usr/bin/env bash #-------------------------------------------------------------- #مدیریت متغیرهای PATH، LD_LIBRARY_PATH، MANPATH ... #نوشته شده به وسیله Emmanuel Rouat <no-email> #(ملهم از مستندات «pathfuncs» در Bash و از این گفتارها: # # #آخرین ویرایش: Sat Sep 22 12:01:55 CEST 2012 # #توابع پایین فاصلهها را به طور صحیح اداره میکنند. #گمان میکنم جای این توابع در عوض .bashrc در .bash_profile است. # #جنبه پیمانهای بودن این توابع گسترش آنها را به مدیریت جایگزینی #مسیر به جای پاک کردن مسیر، آسان میسازد # #جهت توضیح پاک کردن «اقلام دوتایی»، مدخل 43 در اینجا را ببینید: # #(ترفند جالبی است!) #-------------------------------------------------------------- #نمایش $@ (PATH معمولی) در لیست. function p_show() { local p="$@" && for p; do [[ ${!p} ]] && echo -e ${!p//:/\\n}; done } #فیلتر کردن سطرهای خالی، slashهای متعدد ، و مدخلهای تکراری. function p_filter() { awk '/^[ \t]*$/ {next} {sub(/\/+$/, "");gsub(/\/+/, "/")}!x[$0]++' ;} #ساختن دوباره لیستی از مدخلها با جداکننده «:» (شبیه به PATH). function p_build() { paste -sd: ;} #پاک کردن $1 (PATH نوعی) و دوباره ساختن آن function p_clean() { local p=${1} && eval ${p}='$(p_show ${p} | p_filter | p_build)' ;} #حذف $1 از $2 (مبتنی بر stackoverflow، همراه با تغییرات). function p_rm() { local d=$(echo $1 | p_filter) p=${2} && eval ${p}='$(p_show ${p} | p_filter | grep -xv "${d}" | p_build)' ;} #مانند مورد قبل، اما فیلتر بر روی یک الگو (خطرناک، از bin یا / #+به عنوان الگو استفاده نکنید!). function p_rmpat() { local d=$(echo $1 | p_filter) p=${2} && eval ${p}='$(p_show ${p} | p_filter | grep -v "${d}" | p_build)' ;} #حذف $1 از $2 و الحاق نمودن آن به طور پاکیزه. function p_append() { local d=$(echo $1 | p_filter) p=${2} && p_rm "${d}" ${p} && eval ${p}='$(p_show ${p} d | p_build)' ;} #حذف $1 از $2 و پیوست آن به طور پاکیزه به ابتدای $2. function p_prepend() { local d=$(echo $1 | p_filter) p=${2} && p_rm "${d}" ${p} && eval ${p}='$(p_show d ${p} | p_build)' ;} #چند آزمایش: echo MYPATH="/bin:/usr/bin/:/bin://bin/" p_append "/project//my project/bin" MYPATH echo "Append '/project//my project/bin' to '/bin:/usr/bin/:/bin://bin/'" echo "(result should be: /bin:/usr/bin:/project/my project/bin)" echo $MYPATH echo MYOTHERPATH="/bin:/usr/bin/:/bin:/project//my project/bin" p_prepend "/project//my project/bin" MYOTHERPATH echo "Prepend '/project//my project/bin' \ to '/bin:/usr/bin/:/bin:/project//my project/bin/'" echo "(result should be: /project/my project/bin:/bin:/usr/bin)" echo $MYOTHERPATH echo p_prepend "/project//my project/bin" FOOPATH #FOOPATH وجود ندارد. echo "Prepend '/project//my project/bin' to an unset variable" echo "(result should be: /project/my project/bin)" echo $FOOPATH echo BARPATH="/a:/b/://b c://a:/my local pub" p_clean BARPATH echo "Clean BARPATH='/a:/b/://b c://a:/my local pub'" echo "(result should be: /a:/b:/b c:/my local pub)" echo $BARPATH
***
David Wheeler با مهربانی به من اجازه داد از اسکریپتهای آموزندهاش استفاده کنم.
IFS="$(printf '\n\t')" #پاک کردن SPACE، بنابراین با نام فایلهای دارای فاصله خوب کار میکند. #استفاده صحیح از glob: #+همیشه حلقه for، پیشوند برای glob، و کنترل موجودیت را به کار ببرید: for file in ./* ; do #از «./*» استفاده کنید، از * خالی هرگز if [ -e "$file" ] ; then #مطمئن شوید حداقل یک تطابق موجود است. COMMAND ... "$file" ... fi done #اما استفاده صحیح از glob نیازمند الحاقیههای غیر استاندارد bash است. shopt -s nullglob #الحاقیه Bash #+به طوری که globهای بدون تطابق خوب کار میکنند. for file in ./* ; do #از «./*» استفاده کنید، از «*» خالی هرگز COMMAND ... "$file" ... done #این فرمانها، تمام نام فایلها را به درستی اداره میکنند، اگر COMMAND #+بزرگ باشد میتوانند سنگین و بد قواره بشوند: find ... -exec COMMAND... {} \; find ... -exec COMMAND... {} \+ #اگر COMMAND چند فایل را قبول میکند. #این کد نام فایلهای دارای کاراکترهای کنترلی (از جمله سطر جدید و tab) #+را از قلم میاندازد. IFS="$(printf '\n\t')" controlchars="$(printf '*[\001-\037\177]*')" for file in $(find . ! -name "$controlchars"') ; do COMMAND "$file" ... done #اگر نام فایلها نتوانند شامل tabها و سطر جدید باشند قبول است -- #+متوجه فرض باشید. IFS="$(printf '\n\t')" for file in $(find .) ; do COMMAND "$file" ... done #به الحاقیههای غیر استاندارد اما رایج در find و xargs نیاز دارد: find . -print0 | xargs -0 COMMAND #الحاقیههای غیر استاندارد find و shell را لازم دارد (bash کار میکند). #وقتی حلقه به پایان میرسد شاید متغیرها برقرار باقی نمانند: find . -print0 | while IFS="" read -r -d "" file ; do ... COMMAND "$file" #همه جا از "$file" نقلقولی استفاده کنید نه از $file done #الحاقیههای غیر استاندارد find و shell را نیاز دارد (bash کار میکند). #سیستم مورد استفاده باید دارای لوله های با نام (FIFOها)، یا مکانیسم #+/dev/fd باشد. #در این نگارش، متغیرها پس از خاتمه یافتن حلقه بر قرار میمانند، و شما #میتوانید از stdin بخوانید. #+(در صورتیکه fd شماره 4 لازم میشود، 4 را به عدد دیگری تغییر دهید.) while IFS="" read -r -d "" file <&4 ; do COMMAND "$file" #همه جا "$file" نقلقولی به کار ببرید -- نه $file done 4< <(find . -print0) #نگارش لوله با نام. #مستلزم الحاقیههای غیراستاندارد find و read پوسته (bash کار میکند). #سیستم مورد استفاده باید در بر دارنده لولههای با نام (FIFOها)باشد. #یکبار دیگر، در این نگارش، متغیرها پس از پایان حلقه برقرار میمانند و #شما میتوانید از stdin بخوانید. #(اگر fd شماره 4 مورد نیاز است، 4 را به عدد دیگری تغییر بدهید). mkfifo mypipe find . -print0 > mypipe & while IFS="" read -r -d "" file <&4 ; do COMMAND "$file" #همه جا "$file" نقلقولی به کار ببرید -- نه $file done 4< mypipe