Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: villimon в Oct 18, 2013, 19:44



Титла: shell script
Публикувано от: villimon в Oct 18, 2013, 19:44
Здравейте,
не от дълго се занимавам с програмиране и ми казаха да се запозная с Linux не съм много на вътре в нещата и ми трябва малко помощ ако може някои да ми обясни малко.
Въпроса ми е следния мога ли да напиша скрипт на които да му подам име на директория и той да ми изведе всички изпълними файлове в дървото започващо от зададената директория, като дърво с отместване което да отразява нивото на вложеност.


Титла: Re: shell script
Публикувано от: b2l в Oct 18, 2013, 20:45
Код:
#vim test.sh

Код
GeSHi (Bash):
  1. #!/bin/bash
  2. ls -lRa $1

Код:
#chmod +x test.sh
#./test.sh /home

http://tldp.org/LDP/abs/html/localvar.html


Титла: Re: shell script
Публикувано от: dexxa в Oct 18, 2013, 21:02
b2l - това ще листне всичкио
villimon - пробвай на ред 2. от скрипта предложен от b2l да сложиш това:
find $1 -executable -type f

Поздрави


Титла: Re: shell script
Публикувано от: b2l в Oct 18, 2013, 21:20
Опа, не съм допрочел, че търсим изпълними файлове.


Титла: Re: shell script
Публикувано от: neter в Oct 18, 2013, 22:59
Ако държим да е с ls, може например така
Цитат
ls -FRla | grep \*$
или така
Цитат
ls -FRla | grep '*'


Титла: Re: shell script
Публикувано от: villimon в Oct 19, 2013, 09:04
Първо разбирам че съм объркал мястото на темата за което приемете моите извинения.

Благодаря за отговорите,
Ще може ли и няколко разяснения
ls -FRla - тази част от командата разбирам какво прави
но не знам grep '*' - можете ли да ме насочите къде да го прочета или да ми обясните.

командите find $1 -executable -type f извеждат пълния път до файловете има ли начин да се форматира изхода

Примерно имам дървото:

dirHome
    dir1
         dir1_1
         dir1_2
    dir2

и да визуализирам изпълнимите файлове от това дърво с отместване отговарящо на нивото на влюбеност.


Титла: Re: shell script
Публикувано от: neter в Oct 19, 2013, 13:13
А, то трябвало да е в дървовидна структура. Тогава ти е нужен инструментът tree. Инсталирай го, ако нямаш такава команда. Зачети се в изхода от командите 'tree --help' и 'man tree', за да разбереш повече за опциите, които поддържа. За твоите нужди командата може да бъде например така
Цитат
tree -F | grep '[*|/]'

Целта на флага -F както в tree, така и в ls, е да добави знаци за типовете на файловете. На изпълнимите файлове се добавя звездичка (*) и това е причината с grep да указваме да се прихванат редовете, съдържащи звездичка. Понеже искаш да извеждаш и директориите, а директориите съдържат наклонена черта в името си в изходите от ls и tree, затова към grep сега добавих и прихващане на редове, съдържащи наклонена черта. Целта на grep е да отсее ненужните редове и да покаже само търсените, а това, което се подава на grep е прост регулярен израз (regex), указващ съвпадение, ако се съдържа звездичка или (правата черта значи "или") наклонена черта.

П.П.: Може би има нужда да се спомене, че флагът -F добавя звездичка на всички файлове, съдържащи бит за изпълнение, независимо дали този бит е зададен и на трите групи права (потребител-собственик, група-собственик и други) или само на някоя от тях, така че tree и ls ще покажат всички файлове, съдържащи бит за изпълнение, в изхода, независимо дали потребителят, изпълняващ tree и ls, има право да изпълни файла или не.


Титла: Re: shell script
Публикувано от: villimon в Oct 19, 2013, 19:49
Aко tree не е инсталирано на дистрибуцията където стартирам скрипта ще работи ли ?
Aз мисля че може да сложа командата за инсталиране в скрипта, но така ще се инсталира при всяко стартиране
имате ли по добро решение


Титла: Re: shell script
Публикувано от: neter в Oct 19, 2013, 20:17
Не е "free" (като свободен), а "tree" (като дърво) :)

Няма да работи, ако не е инсталирано. Е, би могъл да се направи portable пакет на tree, който да си влачиш в архива, заедно със скрипта и да го викаш с пълен път до мястото, където си го разархивирал, но е излишна, а може да се окаже и относителна, занимавка. Може да добавиш към скрипта проверка дали tree е инсталиран (проверка дали командата я има или дали я има в списъка с инсталирани пакети в системата, или някаква друга проверка или комбинация от проверки за наличност), и ако не е инсталиран, скриптът да го инсталира, след което да се стига до изпълнението на командата с tree. Инсталирането би било най-добре да се прави от хранилищата с пакетния мениджър на системата. Зависи обаче за каква дистрибуция (или дистрибуции) става дума. Debian базираните използват apt, Red Hat базираните използва yum, има и други пакетни мениджъри в други дистрибуции, а има и такива дистрибуции, които нямат пакетни мениджъри. Ако ще се ползват само дистрибуции, ползващи един и същ пакетен мениджър, забиваш в скрипта командата за инсталиране със съответния мениджър в случай, че tree липса, и си готов. Ако ще се ползват дистрибуции с различни пакетни мениджъри, ще трябва да добавиш проверки за вида на пакетния мениджър в текущата система и команди за всеки от необходимите пакетни мениджъри. Ако ще се ползват и дистрибуции без пакетни мениджъри, ще се наложи в скрипта да намесиш и компилиране на tree от изходен код.
И все пак си мисля, че е по-добре да оставиш инсталирането на tree да се случва извън скрипта, като може най-много да сложиш една проверка има ли я командата tree, и ако я няма, да пише, че трябва да се инсталира преди това. Например
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. RESULT=$(tree -F 2>/dev/null | grep '[*|/]')
  4.  
  5. test $? = 0 && echo "$RESULT" || echo 'Резултатът от търсенето е празен или пакетът tree не е инсталиран'
Пълним изхода от tree командата в променливата $RESULT, като насочваме stderr (грешките) към небитието (/dev/null), за да не ни се бъркат в съобщенията. Отдолу командата test проверява дали статусът от изпълнението на предната команда ($?) е равен на нула (което значи, че няма грешки, т.е., командата е налична), и ако е равен на нула, принтира съдържанието на променливата $RESULT, а ако не е равен на нула - принтира съобщението за нуждата от инсталиране. При извеждане на съдържанието на $RESULT може да ползваш и printf, вместо echo, ако изпитваш проблеми със сливане на редовете от изхода в един общ ред от echo.


Титла: Re: shell script
Публикувано от: villimon в Oct 20, 2013, 10:44
Стигнах до тук
Код
GeSHi (Bash):
  1. #! /bin/bash
  2.  
  3. cd .$1
  4.  
  5. dpkg -s tree>&/dev/null
  6.  
  7. if test $? != 0
  8. then echo "Пакетът tree не е инсталиран"
  9.  
  10. else RESULT=$(tree -F 2>/dev/null | grep '[*]')
  11.    if test $? = 0
  12.    then echo "$RESULT"
  13.    else echo 'Резултатът от търсенето е празен'
  14.    fi
  15. fi

имате ли някакви препоръки.


Титла: Re: shell script
Публикувано от: n00b в Oct 20, 2013, 20:44
Има и по-елегантен начин със използването на find:
find . -perm "+1" -type f


Титла: Re: shell script
Публикувано от: villimon в Oct 21, 2013, 07:26
Прав сте изглежда по изящно но идеята ми е да ми изведе само изпълнимите файлове с изместване съответстващо на влюбеността им в дървото.

find ми извежда целия път не съм много добре запознат и съм отворен към всякакви предложения.


Титла: Re: shell script
Публикувано от: n00b в Oct 21, 2013, 13:32
find има още една полза... може да стартира приложение за всеки обект който намери (директория, файл, линк и т.н.).

Така като стартира приложението то ще свърши мръсната работа. Може да използваш awk и да броиш / като ги заместваш със табове и да се получи желания резултат.

Всъщност find е невероятно мощен инструмент за който не подозирах до преди няколко години.


Титла: Re: shell script
Публикувано от: villimon в Oct 21, 2013, 16:34
С awk как може да се преброят директориите до файла


Титла: Re: shell script
Публикувано от: neter в Oct 21, 2013, 22:23
Стигнах до тук
Код
GeSHi (Bash):
  1. ...
  2. dpkg -s tree>&/dev/null
  3. ...
  4. else RESULT=$(tree -F 2>/dev/null | grep '[*]')
  5. ...
имате ли някакви препоръки.
Защо си оставил само звездичката в квадратните скоби? Така ще се покажат само имената на изпълнимите файлове. Нали искаше да се показват и директориите? Демек, вторият цитиран ред от скрипта трябва да е така
Код
GeSHi (Bash):
  1. else RESULT=$(tree -F 2>/dev/null | grep '[*|/]')
А в първия цитиран ред дали не си разменил местата на > и & :)

С други инструменти ще си е играчка да се докара такъв дървовиден вид. Но може да си поиграя, ако ми остане време. Точно това, което изкарва tree ли трябва да се получи или имаш някакви разлики или по-добри идеи в нужния за теб изглед? И какво точно имаш предвид под преброяване на директории?


Титла: Re: shell script
Публикувано от: villimon в Oct 22, 2013, 08:15
Намерих, че >& пренасочва стандартния изход и стандартния изход за грешки. Така беше написано. Искам просто нищо от тази команда да не стига до конзолата.
Искам да се изведат само файловете но да са в дървовидна форма.
n00b казва :
Може да използваш awk и да броиш / като ги заместваш със табове и да се получи желания резултат.
Това не мога да си представя как ще стане.
Иначе tree върши добра работа най-вероятно ще е трудно с други инструменти, защото предполагам този е създаден за такива чели.
Но ми е интересно по какви други начини може да стане, мислех си за обработка на резултата от команда като string но не знам дали изобщо е възможно.
Иначе може ли да питам  Slackware какъв пакетни мениджър използва.


Титла: Re: shell script
Публикувано от: neter в Oct 22, 2013, 11:06
Искам да се изведат само файловете но да са в дървовидна форма.
Ако се извеждат само файловете, по какво ще видиш дървото? Нека изпълним
Код
GeSHi (Bash):
  1. tree -F | grep '[*|/]'
и имаме такъв изход от директории и изпълними файлове
Цитат
├── proba*
├── test/
│   ├── proba1*
│   └── test2/
│       └── proba2*
├── test1/
В този изход файлът proba се намира в основната директория, файлът proba1 се намира в подпапка test, файлът proba2 се намира в подпапка test2 на подпапка test, а подпапка test1 не съдържа изпълними файлове. Ако на grep кажем да остави само файловете (т.е., му укажем само звездичка в квадратните скоби), изходът ще изглежда така
Цитат
├── proba*
│   ├── proba1*
│       └── proba2*
при което се вижда, че proba1 е в подпапка, но не се знае коя. За да знаем коя е папката, може да добавим флаг "-f" към tree, за да се изписва пътят до файла
Код
GeSHi (Bash):
  1. tree -Ff | grep '[*]'
при което изходът ще изглежда така
Цитат
├── ./proba*
│   ├── ./test/proba1*
│       └── ./test/test2/proba2*
Вижда се кой файл е в основната директория, кой файл е в подпапка и имената на директориите се изписват при самите файлове.

Какъв изход предпочиташ - имената на папките да са на отделни редове или да са част от името на файла? Имаш ли нужда от такова визуално представяне на дървото (с линии) или ти е достатъчно просто съответно отместване?


Титла: Re: shell script
Публикувано от: villimon в Oct 22, 2013, 14:20
Лично на мен този вариант
Цитат
├── proba*
├── test/
│   ├── proba1*
│   └── test2/
│       └── proba2*
├── test1/
ми допада най-много но искам да разбера как може да се изведе без линиите със съответното отместване. Ако не те затруднява.


Титла: Re: shell script
Публикувано от: neter в Oct 22, 2013, 16:21
искам да разбера как може да се изведе без линиите със съответното отместване
За да се махнат линиите в изхода на tree и да се запазят отместванията, трябва да се използва някой допълнителен инструмент, който да замени линиите с нещо друго. Например, с инструмента sed и замяна на линиите с интервали
Код
GeSHi (Bash):
  1. tree -F | grep '[*|/]' | sed 's/[├|─|└|│]/ /g'
Ако имаш проблеми с копирането от тук на тези четири знака, оформящи линиите в tree (├, ─, └ и │), въпреки че са UTF-8 и би трябвало да нямаш проблеми, може да си ги копираш от конзолата при теб, когато извикаш tree с налични линии.

П.П.: По-нагоре питаше кой е пакетният мениджър в Slackware. Това е pkgtool ($2).


Титла: Re: shell script
Публикувано от: villimon в Oct 22, 2013, 18:57
Сега ме за гложди въпроса тези символи как си ги написал и примерно не може ли да се заместят с ASCII кода разбирам че sed приема регулярен израз което е string. Дали има друга команда ?


Титла: Re: shell script
Публикувано от: neter в Oct 23, 2013, 00:01
Щом те притеснява директното изписване на тези символи може да ги заместиш с hex стойностите им. Малко по-дълго става, но...
Код
GeSHi (Bash):
  1. a=$(echo '0000000: e294 9c0a' | xxd -r);
  2. b=$(echo '0000000: e294 800a' | xxd -r);
  3. c=$(echo '0000000: e294 940a' | xxd -r);
  4. d=$(echo '0000000: e294 820a' | xxd -r);
  5. tree -F | grep '[*|/]' | sed "s/[$a|$b|$c|$d]/ /g"
Обърни внимание, че съм сменил вида на кавичките в частта със sed (станали са двойни), за да се четат вътре променливите като променливи, а не като текст. Може и с единични кавички, но ще трябва да ги прекъсваме на местата, където са променливите. Командата xxd би трябвало да си е налична в системата и без да качваш допълнителен пакет, но провери все пак.
Нещо не можах да го докарам правилното конвертиране на ASCII стойностите им обратно в тези символи. Ако някой има идея за нещо по-кратко нека сподели.


Титла: Re: shell script
Публикувано от: n00b в Oct 23, 2013, 01:37
пффф.. обърках AWK със SED, но гледам че със neter дерзаете


Титла: Re: shell script
Публикувано от: villimon в Oct 31, 2013, 17:05
Здравейте,
с риск да ви досадя до край ми щукна още един въпрос на който се надявам да можете да ми отговорите.
Има ли начин рекурсивно да обходя дърво на директориите от което да изведа изпълнимите файлове със съответното изместване отговарящо на вложеността.


Титла: Re: shell script
Публикувано от: neter в Oct 31, 2013, 18:04
Има ли начин рекурсивно да обходя дърво на директориите от което да изведа изпълнимите файлове със съответното изместване отговарящо на вложеността.
С какво това се различава от задачата досега?


Титла: Re: shell script
Публикувано от: villimon в Oct 31, 2013, 18:53
идеята ми е вместо с tree да се направи с функция която практически ще прави същото като tree знам, че звучи тъпо ама в това му е интересното да се пресъздаде работата на tree


Титла: Re: shell script
Публикувано от: neter в Oct 31, 2013, 22:38
А, да! Аз нали ти обещах, че ще ти драсна и вариант без tree, ама ей го, трябвало още веднъж да си поискаш, за да се наканя :)
Малко набързо нахвърляно е и може би може да се оптимизира нещо тук-там, но ето с find
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. listArr=( $(find "$1" -perm /a+x -type f | sed 's/\.\///g') )
  4.  
  5. for file in "${listArr[@]}"; do
  6.    pathArr=( $(echo "$file" | sed 's/\//\/ /g') )
  7.    i=0
  8.    for row in "${pathArr[@]}"; do
  9.        printf %$(eval echo $i)s | sed 's/ /    /g'
  10.        echo "$row"
  11.        i=$((i + 1))
  12.    done
  13. done
Това го слагаш в скрипт и викаш скрипта с подаване на папка (променливата $1 служи да прочете подадения първи аргумент към скрипта)
Цитат
./име–на–скрипта.sh "/път/за/търсене"
Може да подаваш както пълен, така и относителен път до папката, в която ще се търси. Даже го изпробвай с двата вида пътища, за да видиш разликата. Забравих да го спомена в предните постове, но това с $1 и подаване на пътя като аргумент към скрипта важи и за примерите с tree (само си добави $1 след -F в реда с tree). Това е стандартният начин за директно подаване на аргументи към скриптове. $1 е първият аргумент, $2 е вторият аргумент и т.н., разделени с интервал в реда, в който извикваш скрипта. Заради отделянето с интервали е хубаво да имаш навика да ограждаш текста на аргументите с кавички, за да не се раздели текстът в отделни аргументи от случайни интервали (каквито може да има в имена на файлове и директории например).

П.П.: Забравих да ти кажа за "-perm /a+x", който можеш да видиш в реда с find. Целта на този аргумент към find е да изведе всичко, което има бит за изпълнение (+x), в която и да е (/a) от групите права (за потребителя-собственик, за групата-собственик или за други потребители), с което се постига като в tree да се извеждат всички изпълними файлове, независимо дали потребителят, изпълняващ скрипта, има право да ги изпълнява или не. Ако искаш да се търсят само изпълними файлове, които потребителят, изпълнил скрипта, има право да изпълнява, тогава замени този аргумент в кавичките с "-executable", т.е., редът с find ще стане
Код
GeSHi (Bash):
  1. listArr=( $(find $1 -executable -type f | sed 's/\.\///g') )
Ако решиш да е с -perm, обърни внимание, че наклонената черта в "/a" е нововъведение във find, което замени плюса (по старому щеше да бъде "+a"), за да удовлетвори едни POSIX спецификации. Едва ли ще ти се наложи, но ако някъде попаднеш на стар find, който не знае за наклонената черта, да знаеш, че е достатъчно да замениш наклонената черта с плюс. Но това, само ако се наложи. Засега в скрипта си го остави по препоръчителния нов синтаксис с наклонената черта.


Титла: Re: shell script
Публикувано от: villimon в Nov 01, 2013, 09:20
Искам нещо такова да направя
filefind ()
{
    for i in *
   do
       if [ -d $i ]
      then j=1;
          while [ $j -le $var ]
         do
             printf "\t"
             j=$[j+1]
         done
      echo $i
      cd ./$i
      eval var=$(( $var + 1 ))
      filefind
       fi
   done
var=$(( $var - 1 ))
cd ..
}

filefind

тази функция рекурсивно обхожда директориите(-d) в дървото и ги извежда. Аз искам да изведе изпълнимите файлове с изместване съответстващо на вложеността. С eval var броя колко навътре се намирам за да знам колко таба да изведа. В тази насока ако може да помогнете.


Титла: Re: shell script
Публикувано от: neter в Nov 01, 2013, 17:17
Извинявай за по-твърдото определение, но това са глупости. Съгласен съм, че твоят скрипт ще ползва по-малко RAM (по-горе в примера с find запазвам целия рекурсивен списък в listArr наведнъж), но колко голям списък ще обхождаш, че това да заима значение и да ти компенсира по-бавните последователни операции? Да не говорим, че ако в някоя подпапка имаш symlink, сочещ към по-горна папка (например, почваш търсенето от /home/test и имаш symlink /home/test/symlink, сочещ към /home/test), ще изпаднеш в безкрайна рекурсия и ще зяпаш безкрайно повтаряща се информация, докато не убиеш ръчно скрипта. Има начин да се избегне, разбира се, но защо ти е да се вкарваш във филми, при цялото удобство и наличие на find във всички дистрибуции?


Титла: Re: shell script
Публикувано от: villimon в Nov 01, 2013, 18:17
Всичко го правя с образователна чел да овладея това онова. Естествено съм съгласен с теб, че тия работи са безсмислени след като има команди като tree и find които освен всичко са оптимизирани. Ще се мъча докато не получа резултат.


Титла: Re: shell script
Публикувано от: neter в Nov 01, 2013, 21:43
Оу, бях останал с впечатлението, че просто търсим нещо, с което да се свърши някаква конкретна работа. Щом е с образователна цел, тогава всичко се променя - много ми харесва скриптът ти в такъв случай :)
Сега, първо някои препоръки в сегашния му вид:
1. Не пренебрегвай началния ред с указател за shell-а, който да се използва при изпълнението на скрипта. Ако оставиш скрипта без такъв ред, тогава скриптът ще се изпълни с shell-а, който потребителят, изпълнил скрипта, използва текущо в конзолата си, а той може не винаги да е shell-ът, чийто синтаксис си следвал при писането на скрипта. Ако си изписал скрипта си напълно със синтаксис, поддържан от всички shell-ове, тогава няма да имаш проблеми, но ако не си сигурен, че си го направил (аз лично никога не съм сигурен, макар че пиша отдавна), указването на този ред ще те спаси от грешки, заради неподдържан синтаксис в shell-а на потребителя. Bash е отличен shell за повечето нужди, вероятно си забелязал, че използвам основно него, но ти си прецени кой shell предпочиташ. Само си провери и напиши синтаксиса спрямо това, което избраният от теб shell поддържа;
2. Не си вмъкнал четене на аргумент с името на началната директория за търсене. Това те принуждава всеки път предварително в конзолата да отиваш до началната папка, в която искаш да търсиш, вместо просто да подадеш пътя (било пълен или относителен) до началната папка към скрипта и всичко да е в една команда. При сегашната структура на скрипта, просто добавяйки в скрипта предварително cd към папката в аргумента няма да те задължи да подаваш аргумент с папката. Ако не подадеш, ще се търси в текущата папка, в която си;
3. Ползвай еднакви отстояния в подредбата на кода в различните редове с еднаква вложеност. В момента кодът ти е разместен, което го прави по-трудно четим, дори и от теб, което може да доведе до загуба на последователността от пишещия и грешни редактирания. Хубаво е да има и по един празен ред между по-основните парчета код за още по-добра видимост, но да речем, че е с по-малка важност от равните отстояния;
4. Винаги дефинирай предварително променливите, които използваш в условия на проверки и цикли, освен ако целта наистина не е недефинирана променлива. Това важи в особена степен за променливите, които ползваш за съхранение на числа, тъй като много числови функции зависят от това стойността да е наистина число, а никога нямаш нужда да сравняваш числово някакво число с нищо. В момента скриптът се оплаква за нечисловата стойност на $var в while, когато for се завърта за първи път. Предварително задаване на $var да е равно на нула те предпазва от началната му нечислова стойност;
5. Отново ти обръщам внимание за нуждата от кавички, когато работиш с имена на файлове и директории (и, въобще, с текстове, които може да съдържат интервали), за да не получиш неочаквани резултати. Освен това принципно е хубаво да използваш кавички за променливите, намиращи се в квадратни скоби, като тези на if и while (не само защото скриптът в момента изкарва грешка и за това);
6. Каква е работата на този eval там? За това сумиране не е нужен eval. Функцията eval служи да превърнеш текст в код. В този ред нямаш такова нещо. Освен това сумиращата функция в bash приема стринговете автоматично за променливи, така че не е нужно да слагаш $ пред var там, но това си е по твоя преценка. За прегледност на кода е хубаво и да си избереш един от двата синтаксиса на сумиращата функция (с двойни кръгли скоби, като при var, или с единични квадратни, като при j;
7. Не е нужно указването на ./ при cd за влизане в поддиректория на текущата. Не е и нужно отместването в дървото да е чак толкова голямо, колкото е табулацията по подразбиране, в конзолата обикновено се използват букви с равна широчина, така че 4 интервала биха били достатъчни като отместване и не биха предизвикали различни отмествания по брой букви в различните редове.

Ето ти го скрипта с приложените предложения, ако нещо не съм го описал ясно, пък ти си решавай кое ще ползваш и кое - не
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. filefind ()
  4. {
  5.    for i in *; do
  6.        if [ -d "$i" ]; then
  7.            j=1
  8.            while [ "$j" -le "$var" ]; do
  9.                printf "    "  
  10.                j=$(( j + 1 ))
  11.            done
  12.            echo "$i"
  13.            cd "$i"
  14.            var=$(( var + 1 ))
  15.            filefind
  16.        fi  
  17.    done
  18.    var=$(( var - 1 ))
  19.    cd ..
  20. }
  21.  
  22. cd "$1"
  23.  
  24. var=0
  25.  
  26. filefind

Сега, за добавянето на изпълнимите файлове към изведения списък. Тук отново имаме двата варианта, спрямо това кои изпълними файлове искаш да се извеждат - тези, които потребителят, изпълнил скрипта, може да изпълнява, или всички файлове, съдържащи бит за изпълнение в някоя от групите права.

Пример за варианта, при който се извеждат само файловете, които потребителят, изпълнил скрипта, може да изпълнява:
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. filefind ()
  4. {
  5.    for i in *; do
  6.        if [[ (-d "$i" && -x "$i" && ! -h "$i") || (-f "$i" && -x "$i") ]]; then
  7.            j=1
  8.            while [ "$j" -le "$var" ]; do
  9.                printf "    "  
  10.                j=$(( j + 1 ))
  11.            done
  12.            if [ -d "$i" ]; then
  13.                echo "$i/"
  14.                cd "$i"
  15.                var=$(( var + 1 ))
  16.                filefind
  17.            else
  18.                echo "$i"
  19.            fi  
  20.        fi  
  21.    done
  22.    var=$(( var - 1 ))
  23.    cd ..
  24. }
  25.  
  26. cd "$1"
  27.  
  28. var=0
  29.  
  30. filefind
Обърни внимание, че съм добавил различно echo, спрямо това дали е файл или директория, за да се различават по някакъв начин в списъка после. Може да си добавиш и други различаващи знаци, ако искаш. Може и да премахнеш разликата, но не те съветвам. А проверките в if-а на ред 6 станаха много, заради защитите от проби за листване на рекурсивни symlink-ове (онези, за които в предния пост ти писах, че ще ти създадат проблеми) и листване на папки, за които потребителят няма права да ги листва (което също би довело до безкраен цикъл).

Пример за варианта, при който се извеждат всички файлове, съдържащи бит за изпълнение в някоя от групите права:
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. filefind ()
  4. {
  5.    for i in *; do
  6.        if [[ (-d "$i" && -x "$i" && ! -h "$i") || (-f "$i" && "$(stat -c %A "$i" 2>/dev/null | grep '[x|s|t]')") ]]; then
  7.            j=1;
  8.            while [ "$j" -le "$var" ]; do
  9.                printf "    "  
  10.                j=$(( j + 1 ))
  11.            done
  12.            if [ -d "$i" ]; then
  13.                echo "$i/"
  14.                cd "$i"
  15.                var=$(( var + 1 ))
  16.                filefind
  17.            else
  18.                echo "$i"
  19.            fi  
  20.        fi  
  21.    done
  22.    var=$(( var - 1 ))
  23.    cd ..
  24. }
  25.  
  26. cd "$1"
  27.  
  28. var=0
  29.  
  30. filefind
Тук използваме командата stat, за да изведем пълния списък от права на съответния файл или папка. Да не те притеснява, малък инструмент е и го има във всяка дистрибуция. В grep съм описал търсене не само на "x" правило, но и на "s" и "t" правило, за да покрием случаите, когато, освен бит за изпълнение, към съответната група права поради някаква причина е зададено и някое от специалните права SUID (ще имаме "s" вместо "x" в правата за потребителя-собственик), SGID (ще имаме "s" вместо "x" в правата за групата-собственик) и sticky bit (ще имаме "t" вместо "x" в правата за други). Ако някое от тези специални права е зададено, но в съответната група права нямаме зададен бит за изпълнение, тогава буквите им биха били големи ("S" и "T"), така че нямаме проблем с това, както сме описали малки букви в grep и не сме задали да не прави разлика между малки и големи букви.

Разбира се, в скрипта може да се обединят и двата варианта на търсене и с аргумент към скрипта потребителят да си избира дали да търси само файловете, които може да изпълнява, или да търси всички файлове, които имат бит за изпълнение в някоя от групите права. Оставям на теб да го направиш, ако ти се занимава, че и без това постът ми стана много дълъг :)