AmigaDOS "wyposażony" jest w multitasking - co znaczy, że możemy uruchomić wiele poleceń lub skryptów jednocześnie. Co jednak zrobić, gdy chcemy jednocześnie uruchomić kilka kopii skryptu, który przerzuca jakieś informacje, zapisując je w plikach tymczasowych, np. zapisuje listę plików do obróbki w pliku tekstowym. Jeżeli uruchomimy kilka kopii tego skryptu jednocześnie, to uzyskane wyniki mogą być "dziwne". Projektanci AmigaDOS przewidzieli taką okoliczność i dają nam możliwość tworzenia skryptów w pełni korzystających z dobrodziejstw multitaskingu - a wszystko to dzięki komendzie/poleceniu/funkcji* <$$> - zwracającej numer procesu, w którym skrypt został uruchomiony (numer okna CLI/Shell), co pozwala na łatwe różnicowanie plików tymczasowych. W poniższym skrypcie przedstawię sposób na zabezpieczenie skryptu przed nadpisywaniem plików tymczasowych w przypadku wielokrotnego, jednoczesnego uruchomienia go.
Starczy tego lania wody - czas na zabawę...
. BackupS - sortowane archiwum
.
.KEY PATH/A,ARCNAME,BACKUPPATH
.BRA {
.KET }
.DEF BACKUPPATH DH1:BACKUP/
; skrypt zaczyna się od komentarza - jeżeli chcemy wstawić komenta przed poleceniem .KEY, to musimy użyć polecenia ". " - gdybyśmy wstawili tam średnik (jak w tym komentarzu), to wywołanie skryptu zakończyłoby się błędem, następnie mamy "pustą linię" - czyli samą . (kropkę).
; polecenie .KEY pozwala nam na przekazanie do skryptu parametrów:
; PATH - ścieżka do katalogu, którego archiwum chcemy wykonać, /A oznacza, że parametr trzeba zawsze podać przy uruchomieniu skryptu,
; ARCNAME - nazwa archiwum,
; BACKUPPATH - katalog, w którym będzie zapisane archiwum.
; za pomocą .BRA i .KET zmieniłem domyślny wygląd nawiasów <> na {}, bo w skrypcie używam redyrekcji > i >> - czyli dla lepszej czytelności kodu skryptu, dlatego też polecenie <$$> będzie wyglądało tak: {$$}.
; Poleceniem .DEF ustawiłem domyślną wartość parametru BACKUPPATH na DH1:BACKUP/, czyli katalog, w którym na Amidze trzymam kopie bezpieczeństwa. Dzięki temu ścieżkę podawać muszę jedynie wtedy, gdy chcę backup zapisać w jakiejś innej ścieżce.
Echo {BACKUPPATH} NOLINE >ENV:ARC{$$}
; tak trochę kuchennymi drzwiami tworzymy zmienną globalną ARC{$$} przy pomocy polecenia Echo - zmienna będzie występować pod nazwą związaną z numerem procesu, w jakim została utworzona. Jeżeli okno Shell, z którego został uruchomiony skrypt, ma numer np. 7 - to zmienna będzie występować pod nazwą ARC7. Do zmiennej zapisujemy wartość parametru BACKUPPATH (czy to domyślną, czy podaną przy uruchomieniu skryptu). Właściwie to nie wiem, dlaczego użyłem tu polecenia Echo a nie SetEnv ARC{$$} {BACKUPPATH}- byłoby szybciej i logiczniej, ale nie czepiajmy się detali.
IF {ARCNAME}NULL EQ NULL
; jeżeli nie podano nazwy dla archiwum to
C:GetDate TIME >>ENV:ARC{$$}
; jako nazwę dla archiwum podaj aktualną datę i czas. Polecenie GetDate pobrałem z Aminetu. Polecenie to wyświetla datę jako ciąg liczb nierozdzielanych żadnymi kropkami, dwukropkami itp. (datę 2011-04-24 14:57:23 przedstawi jako: 20110424145723). Tak wygenerowaną nazwę dopisujemy do zmiennej ARC{$$} (czyli w przypadku naszego przykładowego okna Shell o numerze 7 - ARC7)
ELSE
; jeżeli podano nazwę dla archiwum
Echo {ARCNAME} >>ENV:ARC{$$}
; dopisz nazwę archiwum do zmiennej ARC{$$} (ARC7).
ENDIF
; koniec warunku dla nazwy archiwum
List {PATH} LFORMAT "*"%P%N*"" ALL >T:Lista{$$}
; listujemy zawartość podanego katalogu wraz z podkatalogami i zapisujemy to w pliku Lista{$$} (czyli w przypadku naszego przykładowego okna Shell o numerze 7 - Lista7)
Sort FROM T:Lista{$$} TO T:ListaS{$$}
; sortujemy wygenerowaną listę plików Lista{$$} (czyli Lista7), które chcemy dodać do archiwum i w ten sposób powstaje posortowana ListaS{$$} (ListaS7).
Delete >NIL: T:Lista{$$}
; nieposortowanego pliku Lista{$$} (Lista7) już nie potrzebujemy, więc go usuwamy.
LhA -iT:ListaS{$$} -x -F -b64 -3 -Qa -Qq a $ARC{$$}
; tworzymy archiwum lha zawierające pliki znajdujące się na liście (opcja -iT:ListaS{$$}- czyli -iT:ListaS7) i zapisujemy je w ścieżce i pod nazwą znajdującą się w zmiennej globalnej ARC{$$} (ARC7)
UnsetEnv ARC{$$}
; usuwamy zmienną globalną
Delete >NIL: T:ListaS{$$}
; kasujemy zbędną już posortowaną listę
* - niepotrzebne skreślić ;)
Taki skrypt można uruchomić jednocześnie w wielu oknach CLI/Shell, np. zapuścić backupy wszystkich partycji HD jednocześnie i iść spać - a Ami niech się poci... ;) - bez obawy, że rano w archiwach będą jakieś "miksy" z kilku partycji itp.
Skrypt bez komentarzy znajdziecie w
tym archiwum.