Obsługa argumentów w skrypcie dla zmodyfikowanej funkcji „find”?

3

Korzystam z FreeBSD i rozumiem i używam tej -pruneopcji, findaby zapobiec zejściu polecenia do podkatalogu. Ale uważam, że niezbędna składnia jest bardzo niezdarna i niezręczna. Nie zapobiega również wyświetlaniu samego przyciętego katalogu, który można naprawić, ale irytuje.

Chciałbym utworzyć krótki skrypt / alias, który -noenterspowoduje dodanie nowego argumentu do findpolecenia, jeśli zostanie podany przed innymi podstawowymi (dla uproszczenia).

Chodzi o to, że mogę wpisać dowolny z:

  • find -xs /dir -noenter '$*' -name '*.conf' -ls
  • find -x -s /dir -noenter '$*' -name '*.conf' -ls

i skonwertuje argumenty i wykona:

  • /usr/bin/find -xs /dir \( -name '$*' -prune -or \( -name '*.conf' -and ! \( -type d -and -name '$*' \) \) \) -ls
  • /usr/bin/find -x -s /dir \( SNIPPED \) -ls

ale mogę również normalnie wpisać dowolną rutynową komendę „znajdź” i przekaże ją w sposób przezroczysty /usr//bin/finddo wykonania.

Logicznie skrypt musi zidentyfikować pierwszy argument po nazwie katalogu, a następnie sprawdzić, czy jest to:

  • ... równa się -noenteri następuje co najmniej 2 kolejne argumenty (w takim przypadku wiem, jak zbudować argument, do którego muszę przejść /usr/bin/find, wiedząc, które argumenty były przed nim / po nim); lub
  • ... równa, -noenterale nie następuje po niej jeszcze 2 argumentów (= błąd); lub
  • ... cokolwiek innego lub katalog był ostatnim argumentem lub nie został znaleziony (= przekaż całe oryginalne argumenty do /usr/bin/findniezmienionego).

Mogę to wszystko zrobić z wyjątkiem jednej rzeczy - w jaki sposób kodować część skryptu, która bada argument argv, aby stwierdzić, który numer argumentu (jeśli istnieje) jest dirargumentem?

Mój wybór powłoki dotyczy shskryptów.

Stilez
źródło

Odpowiedzi:

1

Jeśli chcesz przetestować istnienie i lokalizację konkretnego argumentu, wszystko, co musisz zrobić, to przeanalizować wiersz polecenia i przetestować każdy argument pod kątem zgodności z „oczekiwaną” wartością. Tak więc musisz przetestować każdy argument dla wartości, -noentera następnie wydrukować wiersz określający pozycję i nazwę zmiennej -noenter:

for i in `seq 1 $#`; do
    ref=`eval "echo \\$$i"`
    if [ $ref == '-noenter' ]; then echo "arg $i is $ref"; break; fi
done

Teraz to samo, tylko pozycja argumentu -noenterjest przechowywana w, $mitsosa pozycja argumentu przed tym w $mary:

for i in `seq 1 $#`; do
  ref=`eval "echo \\${$i}"`
  if [ $ref == '-noenter' ]; then
    mitsos=$i
    eva=$(($i-1))
    mary=`eval "echo \\${$eva}"`
    break
  fi
done

i teraz $mitsosma pozycję -noenterlub brak wartości oraz $marywartość poprzedzającego argumentu -noenter. W tym momencie, jeśli $maryma wartość /dir, o której wiesz, że jest następny argument -noenteri możesz kontynuować implementację find, w przeciwnym razie użyjesz wersji systemu lub wydrukujesz komunikat o błędzie. Wreszcie, jeśli nie zależy Ci na pozycji -noenter, możesz pominąć linię mitsos=$i.

gmelis
źródło
Dziękujemy za zrozumienie, czego chciałem! Odpowiedź nie jest całkiem w porządku choć. Zakłada, że ​​-noenter jest poprawny w dowolnej pozycji i po prostu go szuka, ale to nie jest poprawne założenie ( find -x -noenter .....powinien to być błąd). Sądzę, że musi sprawdzić arg po „dir”. Prawdopodobnie potrafię to rozgryźć na podstawie tego, co napisałeś, więc jest bardzo blisko. Czy chcesz edytować odpowiedź, aby ją zaakceptować, czy?
Stilez
To nie jest problem, bo w ten sposób będziesz mieć zmienną z pozycji z -noenterlub bez zmiennej. Możesz więc sprawdzić wartość zmiennej $eva, gdzie eva=$(($mitsos-1))i jeśli argument na pozycji $evanie jest równy dir, kontynuuj implementację, w przeciwnym razie korzystasz z systemu. Przeredaguję odpowiedź, aby to odzwierciedlić.
gmelis,
Tego rodzaju prace. Podejrzewam, że biorąc pod uwagę niestandardowy skrypt / mod polecenia, błędne wywołanie można na razie pozostawić jako przypadek na krawędzi :) Nie chciałbym przekazywać go innym do użycia, bez nieco więcej sprawdzania poprawnej składni, ale to jest tylko moje uczucie :)
Stilez
Metoda jest poprawna, ale właśnie stwierdziłem, że instrukcja eval jest nieprawidłowa. nie obsługuje wielu spacji lub> = 10 argumentów. W eval 'echo "${'$i'}" 'zależności od twojego, rozwiązują one problemy: (dane wyjściowe) lub eval 'value="${'$i'}" '(przypisanie). Zauważ, że zakończenie + ponowne uruchomienie znaków cudzysłowu zawiera „$ i” jako wartość zamiast odwrotnego ukośnika + $ powtarzane. Nadal nie obsługuje wyglądów powłoki w wierszu poleceń, np. \(Lub |nie jestem pewien, co można z tym zrobić. Kredyt należy do Ciebie, ale jeśli możesz łatwo zaktualizować, aby naprawić, lub przynajmniej zaktualizować, aby zanotować wyjątki, aby inni mogli uzyskać lepszy wynik, jeśli skorzystają z tej odpowiedzi?
Stilez,
Zaktualizowałem odpowiedź dla ponad 9 argumentów; możesz po prostu użyć nawiasów klamrowych, jeśli nie używasz pojedynczych cudzysłowów, co czasem może być uciążliwe. Ucieczki prawdopodobnie będą większym problemem, a rura najprawdopodobniej łamie interesy, ale zobaczę, czy uda mi się przynajmniej znaleźć sposób na obejście pierwszego.
gmelis,