Jeśli chcesz zbudować swój mandat geek, dołącz do nas na drugą część naszej serii skryptów powłoki. Mamy kilka poprawek, kilka poprawek do scenariusza z zeszłego tygodnia i przewodnik po pętli dla niewtajemniczonych.
W pierwszej części naszego przewodnika po skryptach powłoki, stworzyliśmy skrypt, który skopiował plik do katalogu kopii zapasowej po dodaniu daty na końcu nazwy pliku.
Samuel Dionne-Riel wskazał w komentarzach, że istnieje znacznie lepszy sposób na obsługę naszych zmiennych referencyjnych.
Argumenty są rozdzielane spacjami w powłoce basha, będą się tokenizować, gdy w wynikowym poleceniu rozwiniętym znajduje się spacja. W twoim scenariuszu
cp $ 1 $ 2. $ data_formatted
będzie działał zgodnie z założeniami, o ile zmienne rozszerzone nie zawierają spacji. Jeśli wywołasz swój skrypt w ten sposób:datecp "moje stare imię" "moje nowe imię"
rozszerzenie spowoduje polecenie:cp moje nowe imię moje stare imię.the_date
który ma 6 argumentów.Aby poprawnie rozwiązać ten problem, ostatnia linijka skryptu powinna wyglądać następująco:
cp "$ 1" "$ 2. $ data_formatted"
Jak widać, zmieniając linię naszego skryptu z:
cp -iv $ 1 $ 2. $ data_formatted
do:
cp -iv "$ 1" "$ 2". $ format_daty
zadba o ten problem, używając skryptu do plików, które mają spacje w nazwie. Samuel podkreśla również, że podczas kopiowania i wklejania kodu z tej strony (lub ogólnie Internetu) należy zastąpić właściwe kreski i cytaty dla "typowo lepszych", które często je zastępują. Będziemy także robić więcej, aby nasz kod był bardziej przyjazny dla kopiowania / wklejania. ;-)
Inny komentator, Myles Braithwaite, zdecydował się rozwinąć nasz skrypt, aby data pojawiła się przed rozszerzeniem pliku. Zamiast tego
tastyfile.mp3.07_14_11-12.34.56
otrzymamy to:
tastyfile.07_14_11-12.34.56.mp3
co kończy się nieco wygodniejszym dla większości użytkowników. Jego kod jest dostępny na jego stronie GitHub. Rzućmy okiem na to, co on używa, aby rozdzielić nazwę pliku.
date_formatted = $ (data +% Y-% m-% d_% H% M% S)
file_extension = $ (echo "$ 1" | awk -F. 'print $ NF')
file_name = $ (basename 1 $. $ file_extension)cp -iv $ 1 $ nazwa_pliku- $ format_daty. $ rozszerzenie_pliku
Zmieniłem nieco formatowanie, ale widać, że Myles deklaruje swoją funkcję daty w wierszu 1. W wierszu 2 używa jednak polecenia "echo" z pierwszym argumentem skryptu do wyprowadzenia nazwy pliku. Używa polecenia potoku, aby wziąć to wyjście i użyć go jako wejścia dla następnej części. Po potoku Myles wywołuje polecenie "awk", które jest potężnym programem do skanowania wzorców. Używając opcji -F, mówi polecenie, że następnym znakiem (po spacji) jest to, co zdefiniuje "separator pól". W tym przypadku jest to okres.
Teraz awk widzi plik o nazwie "tastyfile.mp3" jako złożony z dwóch pól: "tastyfile" i "mp3". Wreszcie używa
"print $ NF"
aby wyświetlić ostatnie pole. W przypadku, gdy twój plik ma wiele okresów - dzięki temu awk zobaczy wiele pól - wyświetli tylko ostatni, który jest rozszerzeniem pliku.
W linii 3 tworzy nową zmienną dla nazwy pliku i używa polecenia "basename" do odniesienia wszystkiego w 1 $ z wyjątkiem rozszerzenie pliku. Odbywa się to poprzez użycie podstawowej nazwy i podanie jej 1 $ jako argumentu, a następnie dodanie spacji i rozszerzenia pliku. Rozszerzenie pliku jest dodawane automatycznie ze względu na zmienną, która odwołuje się do wiersza 2. To, co można zrobić, to zrobić
tastyfile.mp3
i zamień go w
smaczny
Następnie w ostatnim wierszu Myles ułożył polecenie, które wyprowadzi wszystko w odpowiedniej kolejności. Zauważ, że nie ma odniesienia do 2 $, drugiego argumentu dla skryptu. Ten konkretny skrypt skopiuje wymieniony plik do twojego bieżącego katalogu. Świetna robota Samuel i Myles!
W naszym artykule o podstawach wspominamy również, że domyślnie skrypty nie mogą być odwoływane jako polecenia. Oznacza to, że musisz wskazać ścieżkę skryptu, aby go uruchomić:
./scenariusz
~ / bin / script
Ale umieszczając swoje skrypty w ~ / bin /, możesz po prostu wpisać ich nazwy z dowolnego miejsca, aby je uruchomić.
Komentatorzy spędzili trochę czasu na debacie nad poprawnością tego, ponieważ żadna nowoczesna dystrybucja Linuksa nie tworzy tego katalogu domyślnie. Ponadto, nikt nie dodaje go do zmiennej $ PATH domyślnie, co jest wymagane, aby skrypty działały jak polecenia. Byłem trochę zaskoczony, ponieważ po sprawdzeniu zmiennej $ PATH, komentatorzy mieli rację, ale wywoływanie skryptów nadal działało dla mnie. Dowiedziałem się, dlaczego: wiele nowoczesnych dystrybucji systemu Linux tworzy specjalny plik w katalogu domowym użytkownika - .profile.
Plik ten jest odczytywany przez bash (chyba że .bash_profile znajduje się w katalogu domowym użytkownika), a na dole znajduje się sekcja, która dodaje katalog ~ / bin / do zmiennej $ PATH, jeśli istnieje. Ta tajemnica zostaje wyjaśniona. W dalszej części serii będę nadal umieszczał skrypty w katalogu ~ / bin /, ponieważ są to skrypty użytkownika i powinny być uruchamiane przez użytkowników. I wydaje się, że naprawdę nie musimy ręcznie mieszać zmiennej $ PATH, aby wszystko działało.
Przejdźmy do jednego z najbardziej użytecznych narzędzi w aranżacji maniaków, aby poradzić sobie z powtarzającymi się zadaniami: pętlami. Dzisiaj będziemy omawiać pętle "dla".
Podstawowy zarys pętli for jest następujący:
dla VARIABLE w LIST; robić
command1
command2
…
commandn
Gotowe
VARIABLE może być dowolną zmienną, chociaż najczęściej małe litery "i" są używane przez konwencję. LISTA to lista przedmiotów; możesz określić wiele elementów (oddzielając je spacją), wskazać zewnętrzny plik tekstowy lub gwiazdką (*) oznaczającą dowolny plik w bieżącym katalogu. Wymienione komendy są wcięte zgodnie z konwencją, więc łatwiej jest zobaczyć zagnieżdżanie - umieszczanie pętli w pętlach (dzięki czemu możesz zapętlić się podczas pętli).
Ponieważ listy używają spacji jako ograniczników - to znaczy, że spacja oznacza przejście do następnego elementu na liście - pliki, które mają spacje w nazwie, nie są zbyt przyjazne. Na razie trzymajmy się pracy z plikami bez spacji. Zacznijmy od prostego skryptu do wyświetlania nazw plików w bieżącym katalogu. Utwórz nowy skrypt w katalogu ~ / bin / zatytułowanym "Loopscript". Jeśli nie pamiętasz, jak to zrobić (w tym oznaczenie go jako pliku wykonywalnego i dodanie hashowania hash bang), zapoznaj się z naszym podstawowym artykułem dotyczącym skryptów bash.
W nim wprowadź następujący kod:
dla i w poz. 1 poz. 2 poz. 3 poz. 4 poz. 5 poz. 6; robić
echo "$ i"
Gotowe
Po uruchomieniu skryptu należy po prostu uzyskać te elementy listy jako dane wyjściowe.
Całkiem proste, prawda? Zobaczmy, co się stanie, jeśli trochę zmienimy sytuację. Zmień swój skrypt, aby brzmiał tak:
dla mnie w *; robić
echo "$ i"
Gotowe
Po uruchomieniu tego skryptu w folderze należy uzyskać listę plików, które zawiera jako wynik.
Teraz zmieńmy polecenie echo na coś bardziej użytecznego - powiedzmy polecenie zip. Mianowicie, dodamy pliki do archiwum. I, dostańmy kilka argumentów w miksie!
dla mnie w $ @; robić
archiwum zip "$ i"
Gotowe
Jest coś nowego! "$ @" To skrót od "1 $ 2 $ 3 ... $ n". Innymi słowy, jest to pełna lista wszystkich podanych argumentów. Teraz zobacz, co się stanie, gdy uruchomię skrypt z kilkoma plikami wejściowymi.
Możesz zobaczyć, które pliki znajdują się w moim folderze. Uruchomiłem polecenie z sześcioma argumentami, a każdy plik został dodany do spakowanego archiwum o nazwie "archive.zip". Łatwo, prawda?
Dla pętli są całkiem wspaniałe. Teraz możesz wykonywać funkcje wsadowe na listach plików. Na przykład możesz skopiować wszystkie argumenty skryptu do spakowanego archiwum, przenieść oryginały do innego folderu i automatycznie zabezpieczyć je przed skopiowaniem na komputer zdalny. Jeśli skonfigurujesz pliki kluczy z SSH, nie musisz nawet wpisywać swojego hasła, a nawet możesz nakazać skryptowi usunięcie pliku zip po jego przesłaniu!
Korzystanie z pętli for ułatwia wykonanie wielu akcji dla wszystkich plików w katalogu. Możesz zestawiać wiele różnych poleceń i bardzo łatwo użyć argumentów do utworzenia listy "w locie", a to tylko wierzchołek góry lodowej.
Skrypty Bash, czy masz jakieś sugestie? Czy zrobiłeś użyteczny skrypt, który używa pętli? Chcesz podzielić się swoimi przemyśleniami na temat serii? Zostaw kilka komentarzy i pomóż innym początkującym skryptom!