3.3 Lekcja 1
Certyfikat: |
Linux Essentials |
---|---|
Wersja: |
1.6 |
Temat: |
3 Siła wiersza poleceń |
Cel nauki: |
3.3 Przekształcanie poleceń w skrypt |
Lekcja: |
1 z 2 |
Wstęp
Do tej pory nauczyliśmy się, jak wykonywać polecenia z powłoki, ale możemy również zapisywać polecenia do pliku, a następnie uczynić ten plik wykonywalnym. Kiedy plik jest wykonywany, wówczas polecenia zapisane w tym pliku są wykonywane w kolejności, jedno po drugim. Te wykonywalne pliki są nazywane skryptami (scripts). Są one podstawowym narzędziem dla każdego administratora systemu Linux. Zasadniczo możemy uznać Bash jako język programowania, podobnie jak powłokę.
Pokaż wyjście
Zacznijmy od zademonstrowania polecenia, które mogłeś zobaczyć w poprzednich lekcjach. Polecenie echo
wypisze argument na standardowe wyjście, tzn. na ekran.
$ echo "Hello World!" Hello World!
Teraz użyjemy przekierowania, aby zapisać to polecenie w nowym pliku o nazwie new_script
.
$ echo 'echo "Hello World!"' > new_script $ cat new_script echo "Hello World!"
Plik new_script
zawiera teraz to samo polecenie, które było wpisane bezpośredio w powłoce.
Tworzenie wykonywalnego skryptu
Pokażemy niektóre wymagane kroki, aby ten plik działał zgodnie z naszymi oczekiwaniami. Pierwszym zadaniem użytkownika jest po prostu wpisanie nazwy skryptu, w taki sposób, w jaki wpisaliby nazwę innego dowolnego polecenia:
$ new_script /bin/bash: new_script: command not found
Możemy bezpiecznie założyć, że plik new_script
istnieje w naszej bieżącej lokalizacji. Zauważ jednak, że komunikat o błędzie nie mówi, że plik nie istnieje, a jedynie informuje, że polecenie nie istnieje. Przydałoby się omówienie, jak Linux obsługuje polecenia i pliki wykonywalne.
Polecenia i ściezka PATH
Na przykład, gdy wpiszemy polecenie ls
w powłoce, wówczas uruchamiamy plik o nazwie ls
, który istnieje w naszym systemie plików. Możesz to sprawdzić, używając argumentu which
:
$ which ls /bin/ls
Wpisywanie bezwzględnej ścieżki dla polecenia ls
za każdym razem, gdybyśmy chcieli spojrzeć na zawartość katalogu, szybko stałoby się męczące. Dlatego Bash ma zmienną środowiskową (environment variable), która zawiera wszystkie katalogi, gdzie możemy znaleźć polecenia, które chcielibyśmy uruchomić. Możesz przeglądać zawartość tej zmiennej używając polecenia echo
.
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
W każdym z tych miejsc, które są oddzielone dwukropkami (:
) powłoka spodziewa się, że znajdzie polecenia. Zauważysz, że katalog /bin
istnieje, ale można bezpiecznie założyć, że nie ma tam naszej bieżącej lokalizacji. Powłoka będzie szukała pliku new_script
w każdym z tych katalogów, ale go tam nie znajdzie, więc wyświetli błąd, który widzieliśmy powyżej.
Istnieją trzy rozwiązania tego problemu: możemy przenieść new_script
do jednego z katalogów PATH
, możemy dodać nasz bieżący katalog do PATH
lub możemy zmienić sposób, w jaki próbujemy wywołać skrypt. Ostatnie rozwiązanie jest najprostsze, ponieważ wymaga od nas jedynie podania bieżącej lokalizacji podczas wywoływania skryptu za pomocą ukośnika (./
).
$ ./new_script /bin/bash: ./new_script: Permission denied
Komunikat o błędzie zmienił się, wskazując, że poczyniliśmy pewien postęp.
Uprawnienia do wykonania
Pierwszym działaniem, jakie użytkownik powinien wykonać w tym przypadku, jest użycie polecenia ls -l
do spojrzenia na właściwości pliku:
$ ls -l new_script -rw-rw-r-- 1 user user 20 Apr 30 12:12 new_script
Widzimy, że uprawnienia do tego pliku są domyślnie ustawione na 664
. Nie ustawiliśmy jeszcze żadnych praw do wykonywania tego pliku.
$ chmod +x new_script $ ls -l new_script -rwxrwxr-x 1 user user 20 Apr 30 12:12 new_script
To polecenie przyznało prawa wykonywania wszystkim użytkownikom. Zauważ, że może to stanowić zagrożenie bezpieczeństwa, ale na razie jest to akceptowalny poziom uprawnień.
$ ./new_script Hello World!
Jesteśmy teraz gotowi do uruchomienia naszego skryptu.
Definiowanie Interpretera
Jak pokazaliśmy, możemy po prostu zapisać tekst do pliku, uczynić plik wykonywalnym i uruchomić. Plik new_script
jest funkcjonalnie nadal zwykłym plikiem tekstowym, ale udało nam się go zmodyfikować, aby był poprawnie nterpretowany przez Basha. Ale co się stanie, jeśli plik jest napisany w Perlu lub w Pythonie?
Bardzo dobrą praktyką jest określenie w pierwszej linii skryptu typu interpretera, którego chcemy używać. Ta linia jest nazywana bang line lub częściej shebang i informuje system, w jaki sposób chcemy, aby ten plik był uruchomiony. Ponieważ uczymy się Basha, będziemy używać bezwzględnej ścieżki do naszego pliku wykonywalnego Bash, ponownie używając polecenia which
:
$ which bash /bin/bash
Nasza linia shebang zaczyna się od znaku hash i wykrzyknika (#!
), po których następuje bezwzględna ścieżka pokazana powyżej. Otwórzmy new_script
w edytorze tekstu i wstawmy tam shebang. Skorzystajmy również z okazji, aby dodać komentarz do naszego skryptu. Komentarze są ignorowane przez interpreter i zostały napisane z myślą o innych użytkownikach, którzy chcą zrozumieć Twój skrypt.
#!/bin/bash # This is our first comment. It is also good practice to document all scripts. echo "Hello World!"
Wprowadzimy również jedną dodatkową zmianę w nazwie pliku: zapiszemy ten plik jako new_script.sh
. Rozszerzenie pliku “.sh” w żaden sposób nie zmienia wykonania pliku. Jest to konwencja, że skrypty bash są oznaczane za pomocą .sh
lub .bash
w celu ich łatwiejszej identyfikacji, tak jak skrypty Pythona są zwykle identyfikowane za pomocą przyrostka .py
.
Typowe edytory tekstu
Użytkownicy Linuxa często muszą pracować w środowisku, w którym nie są dostępne graficzne edytory tekstu. Dlatego zaleca się, aby przynajmniej trochę zaznajomić się z edytowaniem plików tekstowych z poziomu wiersza poleceń. Dwa najpopularniejsze edytory tekstu to vi
oraz nano
.
vi
Program vi
jest szanowanym edytorem tekstu i jest instalowany domyślnie w prawie każdym systemie Linux. Istnieje klon vi
o nazwie vi IMproved lub vim
, który dodaje trochę funkcjonalności, ale zachowuje interfejs vi
. Chociaż praca z edytorem vi
jest trudna dla nowego użytkownika, jednakże edytor jest powszechny i popularny przez użytkowników, którzy poznają jego wiele funkcji.
Najważniejszą różnicą pomiędzy edytorem vi
a aplikacjami takimi jak Notatnik jest to, że vi
ma trzy różne tryby. Podczas uruchamiania klawisze H, J, K oraz L służą do nawigacji, a nie do wpisywania. W trybie nawigacji możesz nacisnąć I i przejść do trybu wstawiania, aby normalnie pisać w edytorze. Aby wyjść z trybu wstawiania, naciśnij klawisz Esc, aby powrócić do trybu nawigacji. W trybie nawigacji możesz nacisnąć :, aby przejść do trybu poleceń. W tym trybie możesz zapisywać, usuwać, zmieniać opcje lub wychodzić z programu.
Chociaż vi
ma tzw. krzywą uczenia się, z czasem różne tryby pozwalają doświadczonemu użytkownikowi na osiągnięcie większej wydajności niż w przypadku innych edytorów.
nano
nano
jest nowszym narzędziem, które jest prostsze i łatwiejsze w użyciu niż vi
. Edytor nano
nie ma różnych trybów. Zamiast tego użytkownik może zacząć pisać podczas uruchamiania i użyć klawisza Ctrl, by uzyskać dostęp do narzędzi widocznych na dole ekranu.
[ Welcome to nano. For basic help, type Ctrl+G. ] ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos M-U Undo ^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Spell ^_ Go To Line M-E Redo
Wybór edytora jest kwestią osobistych preferencji. Edytor, który wybierzesz, nie będzie miał wpływu na tę lekcję. Ale zaznajomienie się z jednym lub kilkoma edytorami tekstu i przyzwyczajenie się do nich przyniesie korzyści w przyszłości.
Zmienne
Zmienne są bardzo ważną częścią każdego języka programowania, podobnie jak Bash. Kiedy rozpoczynasz nową sesję z terminala, powłoka już ustawia pewne zmienne, takie jak zmienna PATH
. Nazywa się je zmiennymi środowiskowymi, ponieważ zwykle definiują właściwości naszego środowiska powłoki. Zmienne środowiskowe możesz modyfikować i dodawać, ale na razie skupimy się na ustawianiu zmiennych w naszym skrypcie.
Zmodyfikujemy nasz skrypt w następujący sposób:
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username=Carol echo "Hello $username!"
W tym przypadku utworzyliśmy zmienną o nazwie username
i przypisaliśmy jej wartość Carol
. Należy pamiętać, że nie ma spacji między nazwą zmiennej, znakiem równości i przypisaną wartością (“username=Carol”).
W następnym wierszu użyliśmy polecenia echo
ze zmienną, ale przed nazwą zmiennej znajduje się znak dolara ($
). Jest to ważne, ponieważ wskazuje powłoce, że chcemy traktować username
jako zmienną, a nie jak zwykłe słowo. Wpisując w naszym poleceniu $username
wskazujemy, że chcemy wykonać podstawienia, zastępując nazwę zmiennej wartością przypisaną do tej zmiennej.
Po uruchomieniu nowego skryptu otrzymujemy następujące dane wyjściowe:
$ ./new_script.sh Hello Carol!
-
Zmienne mogą zawierać tylko znaki alfanumeryczne lub podkreślenia, a także uwzględniają wielkość liter.
Username
orazusername
będą traktowane jako różne zmienne. -
Podstawienie zmiennej może mieć również format
${username}
z dodatkiem{ }
. Jest to również dopuszczalne. -
Zmienne w Bash mają niejawny typ i są traktowane jako ciągi znaków. Oznacza to, że wykonywanie funkcji matematycznych w Bash jest bardziej skomplikowane niż w innych językach programowania, takich jak np. C/C++:
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username=Carol x=2 y=4 z=$x+$y echo "Hello $username!" echo "$x + $y" echo "$z"
$ ./new_script.sh Hello Carol! 2 + 4 2+4
Stosowanie cudzysłowów dla zmiennych
Dokonajmy następującej zmiany wartości naszej zmiennej username
:
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username=Carol Smith echo "Hello $username!"
Uruchomienie tego skryptu spowoduje błąd:
$ ./new_script.sh ./new_script.sh: line 5: Smith: command not found Hello !
Pamiętaj, że Bash jest interpreterem i jak inne tego typu programy, interpretuje nasz skrypt wiersz po wierszu. W tym przypadku Bash poprawnie interpretuje username=Carol
, aby ustawić zmienną username
o wartości Carol
. Ale potem interpretuje spację jako koniec tego zadania, a Smith
jako nazwę polecenia. Aby spacja i nazwa Smith
zostały uwzględnione jako wartość naszej zmiennej, umieścimy wokół nazwy podwójne cudzysłowy ("
).
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username="Carol Smith" echo "Hello $username!"
$ ./new_script.sh Hello Carol Smith!
Ważnym aspektem, na który należy zwrócić uwagę w Bash, jest to, że podwójne cudzysłowy i pojedyncze cudzysłowy ('
) zachowują się bardzo różnie. Podwójne cudzysłowy są uważane za “słabe”, ponieważ pozwalają interpretatorowi na wykonanie podstawienia wewnątrz cudzysłowu. Pojedyncze cudzysłowy są uważane za “mocne”, ponieważ uniemożliwiają jakiekolwiek podstawienie. Rozważmy następujący przykład:
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username="Carol Smith" echo "Hello $username!" echo 'Hello $username!'
$ ./new_script.sh Hello Carol Smith! Hello $username!
W przypadku drugiego polecenia echo
, interpreter nie mógł podstawić $username
zamiast Carol Smith
, więc dane wyjściowe są traktowane dosłownie.
Argumenty
Znasz już użycie argumentów w podstawowych narzędziach Linuxa. Na przykład polecenie rm testfile
zawiera zarówno plik wykonywalny rm
, jak i jeden argument testfile
. Argumenty mogą być przekazywane do skryptu podczas wykonywania i modyfikują sposób działania skryptu. Są łatwe do implementacji.
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username=$1 echo "Hello $username!"
Zamiast przypisywać wartość do username
bezpośrednio w skrypcie, przypisujemy jej wartość nowej zmiennej $1
. Odnosi się do wartości pierwszego argumentu.
$ ./new_script.sh Carol Hello Carol!
W ten sposób traktowanych jest pierwszych dziewięć argumentów. Istnieją sposoby radzenia sobie z więcej niż dziewięcioma argumentami, ale to wykracza poza zakres tej lekcji. Pokażemy przykład tylko dla dwóch argumentów:
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username1=$1 username2=$2 echo "Hello $username1 and $username2!"
$ ./new_script.sh Carol Dave Hello Carol and Dave!
Podczas używania argumentów należy wziąć pod uwagę jedną ważną kwestię: w powyższym przykładzie istnieją dwa argumenty Carol
oraz Dave
, przypisane odpowiednio do $1
oraz $2
. Na przykład, jeśli będzie brakować drugiego argumentu, to powłoka nie zgłosi błędu, a wartość $2
będzie po prostu wynosić zero (null) lub nic.
$ ./new_script.sh Carol Hello Carol and !
W naszym przypadku dobrym pomysłem byłoby wprowadzenie logiki do naszego skryptu, aby różne warunki wpływały na wynik. Zaczniemy od wprowadzenia kolejnej pomocnej zmiennej, a następnie przejdziemy do tworzenia instrukcji if.
Zwracanie liczby argumentów
Podczas gdy zmienne, takie jak $1
oraz $2
, przechowują wartość argumentów pozycyjnych, inna zmienna $#
przechowuje liczbę argumentów.
#!/bin/bash # This is our first comment. It is also good practice to comment all scripts. username=$1 echo "Hello $username!" echo "Number of arguments: $#."
$ ./new_script.sh Carol Dave Hello Carol! Number of arguments: 2.
Logika warunkowa (Conditional Logic)
Zastosowanie logiki warunkowej w programowaniu to obszerny temat i nie zostanie szczegółowo omówiony w tej lekcji. Skoncentrujemy się na składni (syntax) instrukcji warunkowych w Bashu, która różni się od większości innych języków programowania.
Zacznijmy od przeglądu tego, co zamierzamy osiągnąć. Zacznijmy od utworzenia prostego skryptu, który powinien wyświetlić powitanie pojedynczego użytkownika. Jeśli wpiszemy coś innego niż jednego użytkownika, wówczas powinniśmy otrzymać komunikat o błędzie.
-
Warunkiem, który testujemy, jest liczba użytkowników zawarta w zmiennej
$#
. Chcielibyśmy wiedzieć, czy wartość$#
wynosi1
. -
Jeśli warunek jest spełniony i wynosi true (prawda), wówczas działaniem, które podejmujemy, jest powitanie użytkownika.
-
Jeśli warunek nie jest spełniony i wynosi false (fałsz), to otrzymamy komunikat o błędzie.
Teraz, gdy logika jest jasna, przejdźmy do składni (syntax) wymaganej do zaimplementowania tej logiki.
#!/bin/bash # A simple script to greet a single user. if [ $# -eq 1 ] then username=$1 echo "Hello $username!" else echo "Please enter only one argument." fi echo "Number of arguments: $#."
Logika warunkowa jest zawarta między if
a fi
. Warunek do przetestowania znajduje się między nawiasami kwadratowymi [ ]
, a działania, które należy podjąć, jeśli warunek jest spełniony, są wskazane po then
. Zwróć uwagę na spacje pomiędzy nawiasami kwadratowymi i zawartą w nich logikę. Pominięcie tego miejsca spowoduje powstanie błędów.
Ten skrypt wyświetli nasze powitanie lub komunikat o błędzie. Ale zawsze wyświetli wiersz Liczba argumentów
(Number of arguments
).
$ ./new_script.sh Please enter only one argument. Number of arguments: 0. $ ./new_script.sh Carol Hello Carol! Number of arguments: 1.
Zwróć uwagę na instrukcję if
. Użyliśmy -eq
, aby wykonać porównanie numeryczne. W tym przypadku sprawdzamy, czy wartość $#
jest równa jeden. Inne porównania, które możemy wykonać, to:
-ne
-
Nie równa się
-gt
-
Większy niż
-ge
-
Większy bądź równe
-lt
-
Mniejszy niż
-le
-
Mniejszy lub równy
Ćwiczenia z przewodnikiem
-
Użytkownik wprowadza do swojej powłoki:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Co zrobił użytkownik?
-
Które polecenie połączy bieżącą wartość
PATH
z nowym katalogiem~/scripts
?
-
-
Rozważmy następujący skrypt. Zauważ, że do sprawdzenia drugiego warunku jest wykorzystywany
elif
:> /!bin/bash > fruit1 = Apples > fruit2 = Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" > elif [$1 -gt $2 ] then > echo '$fruit1 win!' else > echo "Fruit2 win!" > done
-
Wiersze oznaczone znakiem
>
zawierają błędy. Popraw błędy.
-
-
Jaki będzie wynik w następujących sytuacjach?
$ ./guided1.sh 3 0
$ ./guided1.sh 2 4
$ ./guided1.sh 0 1
Ćwiczenia eksploracyjne
-
Napisz prosty skrypt, który sprawdzi, czy przekazano dokładnie dwa argumenty. Jeśli tak, wypisz argumenty w odwrotnej kolejności. Rozważmy następujący przykład (uwaga: Twój kod może wyglądać inaczej niż ten poniżej, ale powinien dawać takie same wyniki):
if [ $1 == $number ] then echo "True!" fi
-
Ten kod jest poprawny, ale nie jest to porównanie liczb. Skorzystaj z wyszukiwarki internetowej, aby dowiedzieć się, czym różni się ten kod od użycia
-eq
. -
Istnieje zmienna środowiskowa, która wyświetli bieżący katalog. Użyj
env
, aby uzyskać nazwę tej zmiennej. -
Korzystając z tego, czego nauczyłeś się w pytaniach 2 i 3, napisz krótki skrypt, który zaakceptuje argument. Jeśli podano argument, sprawdź, czy jest on zgodny z nazwą bieżącego katalogu. Jeśli tak, wypisz
yes
. W przeciwnym razie wypiszno
.
Podsumowanie
W tej sekcji nauczyłeś się:
-
Jak tworzyć i uruchamiać proste skrypty
-
Jak używać shebang do określenia interpretera
-
Jak ustawić i używać zmiennych w skryptach
-
Jak obsługiwać argumenty w skryptach
-
Jak konstruować instrukcje
if
-
Jak porównać liczby za pomocą operatorów numerycznych
Komendy wykorzystywane w ćwiczeniach:
echo
-
Wyświetla ciąg na standardowym wyjściu.
env
-
Wyświetla wszystkie zmienne środowiskowe na standardowym wyjściu.
which
-
Wyświetla bezwzględną ścieżkę polecenia.
chmod
-
Zmienia uprawnienia do pliku.
Specjalne zmienne używane w ćwiczeniach:
$1, $2, … $9
-
Zawierają argumenty pozycyjne, które są przekazywane do skryptu.
$#
-
Zawiera liczbę argumentów przekazanych do skryptu.
$PATH
-
Zawiera katalogi plików wykonywalnych używanych przez system.
Operatory użyte w ćwiczeniach:
-ne
-
Nie równa się
-gt
-
Większy niż
-ge
-
Większy bądź równe
-lt
-
Mniejszy niż
-le
-
Mniejszy lub równy
Odpowiedzi do ćwiczeń z przewodnikiem
-
Użytkownik wprowadza do swojej powłoki:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Co zrobił użytkownik?
Użytkownik nadpisał zawartość
PATH
katalogiem~/scripts
. W wyniku tego, poleceniels
nie jest już dostępne, ponieważ nie ma go wPATH
. Zwróć uwagę, że ta zmiana ma wpływ tylko na bieżącą sesję. Jeśli wylogujesz się, a następnie zalogujesz ponownie, zmiany zostaną cofnięte, a poleceniels
znowu będzie dostępne. -
Które polecenie połączy bieżącą wartość
PATH
z nowym katalogiem~/scripts
?PATH=$PATH:~/scripts
-
-
Rozważmy następujący skrypt. Zauważ, że do sprawdzenia drugiego warunku jest wykorzystywany
elif
:> /!bin/bash > fruit1 = Apples > fruit2 = Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" > elif [$1 -gt $2 ] then > echo '$fruit1 win!' else > echo "Fruit2 win!" > done
-
Wiersze oznaczone znakiem
>
zawierają błędy. Popraw błędy.#!/bin/bash fruit1=Apples fruit2=Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" elif [ $1 -gt $2 ] then echo "$fruit1 win!" else echo "$fruit2 win!" fi
-
-
Jaki będzie wynik w następujących sytuacjach?
$ ./guided1.sh 3 0
Apples win!
$ ./guided1.sh 2 4
Oranges win!
$ ./guided1.sh 0 1
This is like comparing Apples and Oranges!
Odpowiedzi do ćwiczeń eksploracyjnych
-
Napisz prosty skrypt, który sprawdzi, czy przekazano dokładnie dwa argumenty. Jeśli tak, wypisz argumenty w odwrotnej kolejności. Rozważmy następujący przykład (uwaga: Twój kod może wyglądać inaczej niż ten poniżej, ale powinien dawać takie same wyniki):
if [ $1 == $number ] then echo "True!" fi
#!/bin/bash if [ $# -ne 2 ] then echo "Error" else echo "$2 $1" fi
-
Ten kod jest poprawny, ale nie jest to porównanie liczb. Skorzystaj z wyszukiwarki internetowej, aby dowiedzieć się, czym różni się ten kod od użycia
-eq
.Użycie
==
spowoduje porównanie ciągów (strings). Oznacza to, że jeśli znaki obu zmiennych są dokładnie takie same, to warunek jest prawdziwy.abc == abc
true
abc == ABC
false
1 == 1
true
1+1 == 2
false
Porównania ciągów prowadzą do nieoczekiwanego zachowania podczas testowania liczb.
-
Istnieje zmienna środowiskowa, która wyświetli bieżący katalog. Użyj
env
, aby uzyskać nazwę tej zmiennej.PWD
-
Korzystając z tego, czego nauczyłeś się w pytaniach 2 i 3, napisz krótki skrypt, który zaakceptuje argument. Jeśli podano argument, sprawdź, czy jest on zgodny z nazwą bieżącego katalogu. Jeśli tak, wypisz
yes
. W przeciwnym razie wypiszno
.#!/bin/bash if [ "$1" == "$PWD" ] then echo "yes" else echo "no" fi