Blog poświęcony głównie tematyce związanej z informatyką oraz użytkowymi aspektami komputerów i Internetu.
Creative Commons License
Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Użycie niekomercyjne-Bez utworów zależnych 2.0 Polska

darmowe liczniki
Kategorie: Wszystkie | informatyka | przemyślenia | użytkowe
RSS
piątek, 08 marca 2013
Switch to English + new main blog

I have decided to publish new blog posts only in English. I have always been trying to provide information that can be useful for other people. Writing only in Polish language hinders me from reaching my target audience. Which can potentially be everywhere, not only in my country. In my experience I have already come across situations when I find something useful and cannot benefit from it, because it is written only in German or only in Italian. I would not like to make such mistakes. English language is the most appropriate tool for establishing connection with and reaching people worldwide. I also do believe my Polish readers will not suffer much Puszczam oczko as knowledge of English in my country is not too bad.

UPDATE -- March 18, 2013. I have started new technical blog: blog.pjsen.eu. All new technical content will be published there in English. Here some minor, Polish-specific thoughts will be shared.

poniedziałek, 23 stycznia 2012
Wątpliwości dot. rozwiązań open-source

Oprogramowanie o otwartym kodzie źródłowym, jak by się mogło wydawać, budzi ogromny entuzjazm zarówno wśród programistów, jak i użytkowników. Programiści przykładowo mają możliwość korzystania z potencjału drzemiącego w ogólnodostępnym dla wszystkich kodzie źródłowym. W przypadku zaś darmowych narzędzi i bibliotek -- w znaczący sposób zmniejszają one koszty wytwarzania oprogramowania. Jakby tego było mało, można liczyć na pomoc przyjaźnie nastawionej społeczności innych entuzjastów, która gotowa jest pomóc nawet w najcięższych przypadkach. Jak by się mogło wydawać, również użytkownicy oprogramowania o otwartym kodzie źródłowym powinni być wielce usatysfakcjonowani, ponieważ nie dość, że mają produkt za darmo, to jeszcze mają świadomość, iż został on stworzony przez prawdziwych specjalistów, pracujących nad rozwojem programu "z potrzeby serca".

Niestety, jak to w życiu bywa, pozory mylą i powyższy obraz jest czysto teoretyczny. Nie będę omawiać wątpliwości dot. aspektów użytkowych oprogramowania open-source, ponieważ jest to temat na oddzielny post. Chciałbym skupić się na zagadnieniach istotnych z punktu widzenia programisty oraz podać konkretny przykład, który mnie osobiście zabolał.

W ostatnim czasie spotkałem się z opinią zawodowego programisty, iż korzystanie z rozwiązań open-source w poważnym komercyjnym projekcie może być ryzykowne, kosztowne, a nawet szkodliwe. Uzasadniając swoje zdanie, programista ten przedstawił kilka konkretnych zarzutów:

  1. Nikt osobiście nie bierze odpowiedzialności za zagwarantowanie rozwoju, uaktualnień oraz wsparcia dla rozwiązań open-source. Podany został przykład sytuacji, gdy w pracach nad komercyjnym projektem szeroko wykorzystywano darmową bibliotekę. W pewnym momencie wydana została nowa wersja biblioteki, całkowicie niekompatybilna z poprzednią. Autor biblioteki całkowicie "odciął" się od starej wersji i zaprzestał jej utrzymywania. Zespół stanął przed dramatycznym wyborem: korzystać ze starej wersji narażając się na wszelkie kłopoty z tym związane, czy całkowicie przepisać projekt, tak by korzystał z nowej wersji. Wybrano to drugie rozwiązanie, co z punktu widzenia rozwoju stanowiło półroczny przestój.
  2. Wsparcie społeczności również nie jest czymś, co może być w jakikolwiek sposób zagwarantowane. Czasami bywa też tak, że projekt "umiera" i nikt, z autorem włącznie, już się nim nie interesuje. Wtedy nawet nie wiadomo do kogo zwrócić się w przypadku problemów.
  3. Otwarty kod źródłowy wcale nie oznacza szybszego reagowania na błędy. Znane są przypadki, gdy autorzy całkowicie ignorowali błędy znajdowane przez użytkowników. Programiści musieli poprawiać znaleziony przez nich samych błąd w bibliotece samodzielnie kompilując każdą kolejną jej wersję, tak aby nadawała się do użytku w ich projekcie. Skutkiem tego było to, iż zespół przeznaczony do prac nad projektem de facto pracował nad dwoma projektami: właściwym projektem + biblioteką, która była im potrzebna.
  4. Dokumentacja w przypadku open-source to jest coś, co może istnieć, ale wcale nie musi.
  5. Opublikowany przez autora kod źródłowy może być w postaci kompletnie nieutrzymywalnej. I na przykład może się wcale nie kompilować. Takie przypadki też istnieją.

Wyżej wymieniłem najważniejsze, potencjalne problemy, jakie można na siebie sprowadzić korzystając z rozwiązań open-source. Oczywiście nie należy generalizować i postrzegać wszystkich rozwiązań przez pryzmat tego typu kłopotów. Niemniej jednak zamiast entuzjastycznie skakać z radości, warto mieć świadomość ryzyka.

Osobiście boleśnie doświadczyłem pierwszego i czwartego z opisywanych problemów. W ramach pracy magisterskiej tworzyłem proste narzędzie do symulacji błędów działające w trybie jądra systemu Linux. Nie wnikając za bardzo w szczegóły, jest to rozwiązanie zbliżone koncepcyjnie do klasycznych debugger'ów, jednakże zamiast wykorzystywać API systemu operacyjnego (kwestie wydajnościowe w przypadku narzędzi programowej symulacji błędów) implementuje własne mechanizmy modyfikujące procedury obsługi przerwań poprzez patch'owanie kodu jądra "w locie". Bazowym mechanizmem w tym rozwiązaniu jest ustawianie brakpoint'ów sprzętowych. Jądro udostępnia do tego celu elegancką funkcję register_user_hw_breakpoint. Super. Tylko, że ta funkcja, choć należy do API jądra od wersji 2.6.33 jest nieudokumentowana. Próżno szukać jej opisu na stronie dedykowanej API na kernel.org/doc. Jedynym dokumentem jest chyba artykuł z Linux Symposium dostępny w wielu miejscach w internecie (m.in. http://kernel.org/doc/ols/2009/ols2009-pages-149-158.pdf), który stanowi wstęp koncepcyjny autorstwa deweloperów odpowiedzialnych za implementację mechanizmu.

Aby funkcja utworzyła breakpoint sprzętowy na instrukcji wykonywalnej, jako wielkość należało jej podać stałą HW_BREAKPOINT_LEN_1. Tak było w wersjach jądra od 2.6.33 do 2.6.35. Problem zaczął się, gdy przetestowałem swój program na nowszych wersjach. Funkcja po prostu przestała działać. Nigdzie nie udało mi się znaleźć żadnych informacji, czy, jak i dlaczego interfejs uległ zmianie. Co gorsze, nigdzie w jądrze nie było wywołań tej funkcji z takim zestawem parametrów, jakiego używałem ja. Nie było więc niczego, na czym można by się wzorować. Przyznam, że straciłem sporo czasu analizując kod jądra w poszukiwaniu jakichkolwiek wskazówek, co mogło się stać. Miałem szczęście. Znalazłem. Okazuje się, że od wersji jądra 2.6.36 w przypadku pułapek sprzętowych, rozmiar musi być ustawiony jako sizeof(long), a nie jako wartość ww. stałej. Świetnie. Taka mała, ale niesamowicie złośliwa, nieudokumentowana, funkcjonalna zmiana w interfejsie API. Chyba jedna z gorszych rzeczy, jakie mogą spotkać programistę. Ale ja i tak miałem szczęście, moje rozwiązanie jest stosunkowo proste. Wywoływałem tę funkcję tylko 2 razy. Aż boję się pomyśleć co by było, gdyby coś takiego zdarzyło się podczas rozwoju naprawdę dużego projektu.

Zwolennicy open-source oraz członkowie społeczności deweloperów jądra mogą w tym miejscu zarzucić mi, że jestem amatorem, bo modyfikacja ta na pewno *gdzieś* jest opisana w jakimś commicie do repozytorium kodu jądra. A poza tym, to sam sobie jestem winien, bo interfejs programistyczny jądra jawnie nie gwarantuje kompatybilności pomiędzy różnymi wersjami jądra zarówno na poziomie funkcji jak i ABI. Owszem, wiem o tym. Tylko, czy to przypadkiem nie jest kolejne potwierdzenie, że stosowanie rozwiązań open-source może (oczywiście nie musi) wiązać się z dodatkowymi, nieprzewidywalnymi kłopotami?

wtorek, 10 stycznia 2012
Systemu po hibernacji nie da się używać

Spotkałem się wielokrotnie z narzekaniami użytkowników systemu Windows, że po zastosowaniu hibernacji ich system zaczyna działać bardzo wolno i praktycznie nie nadaje się do użytku. Użytkownicy ci twierdzą, że problemy te są tak dokuczliwe, że nie korzystają z hibernacji w ogóle. W dzisiejszym wpisie chciałbym spojrzeć od strony technicznej na możliwe przyczyny takiego stanu rzeczy i zasugerować sposoby jeśli nie całkowitego, to przynajmniej częściowego zwalczenia problemu.

Na początku zwrócę również uwagę, że zdumiewająco mało osób korzysta z hibernacji i / lub usypiania komputera. Osobiście nie wyobrażam sobie życia bez tych dwóch opcji i nigdy (poza historyczną już wersją systemu Windows 2000, gdzie mechanizm hibernacji nie działał prawidłowo na wielu komputerach) nie doświadczyłem żadnych problemów z nimi związanych. Z użytkowego punktu widzenia często, gdy pracuję z użyciem kilkunastu aplikacji na raz, mając otwartych wiele różnych plików, to nie wyobrażam sobie codziennego uruchamiania i otwierania tego wszystkiego. Osobiście prawie nigdy nie wyłączam komputera zamykając jednocześnie system. Najczęściej usypiam komputer, w przypadku notebooka i odłączeniu go od zasilania zapewnia mu możliwość wykorzystywania akumulatorów, co jest dla nich dodatkowo korzystne. Gdy z jakichś przyczyn nie mogę uśpić komputera (akumulator jest zepsuty), a nie ma sensu usypiać laptopa podłączonego do prądu, wtedy używam hibernacji. Efekt końcowy jest w zasadzie identyczny.

W zasadzie, ponieważ, jak twierdzą niektórzy użytkownicy, po odhibernowaniu komputer zaczyna działać bardzo wolno. Kluczem do zrozumienia, dlaczego faktycznie komputer ma prawo zacząć działać wolno jest uświadomienie sobie pewnych specyficznych mechanizmów zarządzania pamięcią we współczesnych systemach operacyjnych, których działanie nie jest intuicyjne.

Hibernacja polega na zapisaniu zawartość używanej części pamięci fizycznej na dysk i wyłączeniu komputera. Wbrew pewnym opiniom, które napotkać można w Internecie, hibernacja z punktu widzenia sprzętowego powoduje takie samo wyłączenie komputera, jak opcja zamykania systemu. To system operacyjny jest odpowiedzialny za zrealizowanie całej operacji. Podczas normalnego działania systemu operacyjnego tylko część zarezerwowanej przez programy pamięci jest  faktycznie zajmowana w pamięci fizycznej. Pozostała, ta mniej używana część jest przenoszona do pliku wymiany, na dysk twardy. W razie potrzeby, rzadziej używane fragmenty pamięci są "sprowadzane" z powrotem do pamięci fizycznej. Mechanizm ten nazywa się stronicowaniem na żądanie i pozwala na zoptymalizowane wykorzystanie pamięci fizycznej. Oprócz tego, gdy system operacyjny działa przez dłuższy czas, w pamięci fizycznej znajdują się nie tylko uruchomione programy, ale również bufor (ang. cache) operacji dyskowych. Bufor ten jest częścią pamięci fizycznej używanej przez system (ang. system working set) i podczas hibernacji jest zapisywany na dysk. Pamięć, która podawana jest w systemowym menedżerze zadań jako wolna w rzeczywistości też jest używana przez system. Jest tam tzw. standby list. Gdy system decyduje o przeniesieniu nieużywanej pamięci do pliku wymiany, owszem oznacza ją jako nieużywaną, ale zachowuje jej zawartość, tak na wszelki wypadek, gdyby trzeba było z niej *szybko* skorzystać (bo skorzystać można i tak, tylko, że sprowadzenie tego obszaru z pliku wymiany jest czasochłonne). Zarządzanie systemem buforowania w Windows wykonywane jest przy użyciu tego samego mechanizmu, który zarządza pamięcią. W związku z tym, część zawartości bufora plików, która przestaje być używana, również przenoszona jest do standby list, tak na wszelki wypadek, gdyby w przyszłości była potrzebna.

Gdy system działa przez dłuższy czas, standby list zapełnia prawie całą nieużywaną pamięć fizyczną, powodując, że wszystkie dane, które potencjalnie mogą być w każdej chwili potrzebne są obecne w pamięci fizycznej, do której dostęp jest bardzo szybki. Po długim działaniu komputera, mając uruchomione cały czas te same programy i wykonując takie same operacje, standby list w "inteligentny" sposób zapełnia pamięć komputera powodując płynne i szybkie działanie uruchomionych programów.

W tym momencie zbliżamy się do wyjaśnienia zagadki powolnego działania po odhibernowaniu. Przy hibernacji zapisywana jest tylko pamięć używana przez programy, czyli ta, która jest raportowana przez system jako faktycznie zajęta. Standby list nie jest zapisywana. Odhibernowany system musi ponownie załadować z dysku dane, które były zbuforowane w nieużywanej części pamięci. Nie ma możliwości wpłynięcia na zawartość standby list, więc w tym temacie niczego nie da się zmienić. Ale jest jeszcze jedno spostrzeżenie: gdy raportowane przez system zużycie pamięci jest duże, to zapewne plik wymiany również jest w znacznym stopniu wykorzystywany. Przed zahibernowaniem, jak wspomniałem, część danych przeniesionych na dysk do pliku wymiany znajduje się jeszcze w pamięci w standby list. Po zahibernowaniu i odhibernowaniu, wszystkie żądania sprawdzenia nieużywanych obszarów pamięci z pliku wymiany będą również skutkowały faktyczną operacją dyskową odczytu, co jest czasochłonne z punktu widzenia wykonywania programów. Jest to powód spowolnionego działania komputera po odhibernowaniu.

W jaki sposób tego uniknąć? Osobiście staram się nie hibernować systemu z bardzo dużym zużyciem pamięci. Dzięki temu przynajmniej częściowo eliminuję narzut czasowy potrzebny na sprowadzenie z pliku wymiany potrzebnych obszarów pamięci. Trudno podać mi konkretne liczbowe zalecenia, ale z moich doświadczeń wynika, że hibernowanie przy zużyciu pamięci mniejszym niż 50% nie powinno sprawiać absolutnie żadnych problemów po odhibernowaniu. Przed zahibernowaniem polecam więc użycie menedżera zadań, wybranie kilku najbardziej pamięciożernych aplikacji i zamknięcie ich. Najlepszymi, uniwersalnymi kandydatami na sam początek są przeglądarki internetowe, programy pocztowe i komunikatory. U mnie to działa.

PS. Problemy te nie dotyczą usypiania komputera, ponieważ wtedy zawartość pamięci fizycznej jest zachowywana (pamięć jest wtedy jedyną częścią komputera, która pozostaje zasilana).

piątek, 08 lipca 2011
Cieszysz się, że Twój tablet obsługuje bluetooth? Spokojnie...

Chciałbym przedstawić zdumiewające zagadnienie dotyczące obsługi bluetooth w tablecie Creative ZiiO 7. Co prawda jest to urządzenie z dolnej półki jeśli chodzi o tablety, niemniej jednak w mojej ocenie jest całkiem funkcjonalne. Niestety okazało się, że niektóre funkcjonalności są rozumiane przez producenta w nieco odmienny sposób niż mogłoby się to wydawać.

Problem dotyczy przesyłania plików z komputera do urządzenia poprzez bluetooth. Mówiąc krótko nie da się. Wysyłanie plików w systemie Windows kończy się błędem. Rzecz jasna, urządzenia są sparowane i "widzą się". Co ciekawe, smartfon Nokia potrafi wysłać pliki do tabletu ZiiO bez żadnych problemów. Wystosowałem w tej sprawie następujące zapytanie do obsługi klienta firmy Creative:

I have a problem when connecting the device with 64-bit Windows 7 PC via bluetooth. The computer cannot send files to ZiiO. The configuration of computer OS is absolutely correct because it can clearly send files via bluetooth to Nokia smarphone. Furthermore, the Nokia smartphone can send files to the ZiiO, so it prooves that ZiiO is also properly configured. It seems that there is some issue with Microsoft bluetooth stack (i use default Windows tools to send files via bluetooth) and Android

Odpowiedź, którą otrzymałem jest jak następuje (podkreślenia moje):

May I know what file type have you transferred from your Nokia Smartphone to your ZiiO unit?
Was it transferred just by pairing the devices via bluetooth?
Please take note that the bluetooth feature of the ZiiO tablet is meant for streaming high fidelity stereo wirelessly to all compatible stereo Bluetooth speakers and headphones such as the ZiiSound D5, ZiiSound T6 and Creative WP-300 Headphones. It was never meant for file transferring.

Czy firma Creative jest w porządku? Formalnie tak, na jej stronie widnieje następujący opis feature'a tabletu związanego z bluetooth:

Bez przewodów, bez problemów - tylko nieskazitelna muzyka odtwarzana poprzez Bluetooth Dzięki wykorzystaniu technologii Bluetooth oraz apt-X urządzenie ZiiO 7" zapewnia wysoką  wierność muzyki odtwarzanej bezprzewodowo. Urządzenie to może współpracować ze stereofonicznymi głośnikami Bluetooth - takimi jak głośniki Creative ZiiSound D5 oraz ZiiSound T6 - a także stereofonicznymi słuchawkami Creative WP-300.

(źródło: http://pl.store.creative.com/urzadzenia-multimedialne-odtwarzacze-mp3/ziio-7/948-20231.aspx)

Nie znam się na szczegółach technicznych implementacji stosu bluetooth. Niemniej jednak uwagę zwraca puste okienko usług dostępnych na sparowanym z komputerem tablecie:

ZiiO Właściwości

Poniżej lista usług smartfonu:

Nokia E-72

ZiiO jest tabletem pracującym pod kontrolą systemu Android w wersji 2.2. Funkcjonalność przesyłu plików przez bluetooth jest na standardowym wyposażeniu tego systemu, idę o zakład, że potrafi to każdy telefon z tym systemem. Wygląda na to, że firma Creative celowo zmodyfikowała implementację stosu bluetooth systemu Android tak, aby urządzenie nie obsługiwało żadnych usług bluetooth poza ich własną polegającą na jakimś niby cudownym przesyłaniu dźwięku.

Zagadnienie działającego przesyłu w kierunku smartfon Nokia -> tablet nie jest dla mnie do końca jasne. Być może implementacja stosu bluetooth w systemie Symbian jest tak skonstruowana, że rozpoczyna przesył pliku, nawet jeśli docelowe urządzenie nie "chwali się" tym, jakie usługi są na nim dostępne.

Chciałbym pogratulować z tego miejsca pomysłowości producentowi. Nie ma to jak zmodyfikować implementację technologii, która ma dziesiątki zastosowań tak, aby nadawała się tylko do jednego z tych zastosowań. Moim zdaniem producent powinien pójść w dokładnie przeciwnym kierunku i wręcz rozszerzyć obsługę bluetooth np. o dial-up networking, co umożliwiłoby podłączenie urządzenia do internetu poprzez dowolny telefon komórkowy. AFAIK nie jest to możliwe w systemie Android w wersji 2.2, natomiast coś takiego potrafi (co prawda po zainstalowaniu dodatkowego oprogramowania) konkurencja spod znaku jabłka -- iPad. Oczywiście nie mam zamiaru załamywać się z powodu problemów z transferem, ponieważ istnieją rewelacyjne programy takie jak WiFi File Explorer, które umożliwiają przesyłanie plików szybciej i łatwiej niż przez bluetooth, niemniej jednak chciałbym zwrócić uwagę na niepokojący trend we współczesnej elektronice użytkowej polegający na tym, że producenci w coraz bardziej drastyczny sposób zaczynają ograniczać to, jak klient może używać ich produktu.

PS. Nie czuję się aż tak bardzo poszkodowany. Podobno konkurencja spod znaku jabłka też nie potrafi przesyłać plików przez bluetooth.

niedziela, 22 sierpnia 2010
Prowizoryczne rozwiązanie problemu polskich znaków w plikach epub dla wersji oprogramowania 0.35 czytnika Jetbook

Z przygotowanego przeze mnie rozwiązania skorzystają zapewne tylko użytkownicy tego całkiem dobrego sprzętu do czytania ebook'ów. Jednakże, aby zachować wartość merytoryczną tego wpisu dla wszystkich czytelników, w drugiej części opisuję swoje spostrzeżenia i uwagi dotyczące tworzenia skryptów wiersza poleceń w systemie Windows.

a

2. Problemy przy rozwiązywaniu problemu, czyli pisanie skryptu wiersza poleceń

Gdy w różnych pseudo-fachowych poradnikach spotyka się porównania systemu Windows do systemu Linux to bardzo często zawarte są tam stereotypowe stwierdzenia, że w systemie Windows wiersz poleceń jest bezużyteczny, zaś w systemie Linux ma ogromne możliwości. W takich sytuacjach nie mogę oprzeć się refleksji, że autorzy takich porównań po pierwsze chyba nigdy sami nie napisali żadnego skryptu, a po drugie pewnie nie słyszeli, że od paru lat Windows ma Powershell, który jest de facto bardzo potężną powłoką. Poniżej postaram się pokazać kilka argumentów za tym, że standardowy interpreter poleceń systemu Windows jest jednak użyteczny, aczkolwiek ciężko.

2.1 Zapisywanie wyniku działania polecenia do zmiennej

Przykładowy przypadek użycia: wiemy, że w katalogu znajduje się plik wykonywalny (z rozszerzeniem .exe), ale nie wiemy jak się nazywa.

Kod cmd:

   1: for /f %i in ('dir *.exe /b') do @set x=%i
   2: echo %x%

Kod sh:

   1: x=`ls *.exe`
   2: echo $x

Jest to dziwactwo straszliwe: aby zapisać wynik do zmiennej trzeba. użyć pętli for. Koniecznie z przełącznikiem /f, który to umożliwia. Problem pojawia się, gdy wynik polecenia jest wielowierszowy. Przyznam, że nie zastanawiałem się nad tym, ale pewnie trzeba jeszcze bardziej kombinować. W powłoce Unix'a rzecz prosta i oczywista, bez żadnych dodatkowych komplikacji.

2.2 Różnice w semantyce poleceń

W cmd jest polecenie ren, które służy do zmiany nazwy pliku. W sh jest polecenie mv, które służy do przenoszenia plików, a w szczególności do zmiany ich nazwy. W sh w poleceniu mv możemy podać pełne ścieżki do plików. W ren ścieżkę podajemy tylko do pierwszego argumentu, drugi - czyli nowa nazwa *musi* być bez ścieżki. Żeby było ciekawiej w cmd jest też polecenie move, które działa tak samo jak mv z sh. Niby mało istotny szczegół, ale może spowodować nieoczekiwane wykolejenie się skryptu.

2.3 Liczenie w skrypcie

Przykładowy przypadek użycia: tworzenie zmiennych nazw plików w skrypcie.

Kod cmd:

   1: set a=0
   2: set /a a+=1

Kod sh:

   1: a=0
   2: a=`expr $a + 1`

Jak widać w cmd można liczyć. Polecenie set zostało unowocześnione i obsługuje teraz wyrażenia. Aczkolwiek, gdy ktoś tego nie wie i zabiera się za pisanie skryptu to jest mała szansa, że wpadnie na to, że trzeba użyć akurat polecenia set. Moim zdaniem język powłoki unixowej znów jest bardziej czytelny, prosty i logiczny. Używamy podstawowego mechanizmu: znaków akcentu i specjalnego polecenia, które służy do liczenia.

2.4 Podstawianie wartości zmiennych przez interpreter

Przykładowy przypadek użycia: wykorzystywanie w pętli for wartości pewnej zmiennej oraz modyfikacja tej wartości.

Kod cmd:

   1: set a=0
   2: for %s in (.\fixed_ebook\*.html) do (
   3: set /a a+=1
   4: echo %a%
   5: )

Świetnie. Tylko, że ten kod nie działa. Trochę czasu i nerwów straciłem zanim dotarłem do wytłumaczenia zawartego w pomocy do polecenia set. Otóż interpreter cmd podstawia wartość zmiennej w momencie wczytywania linii z poleceniem, a nie jej wykonania. Wczytuje polecenie for, podstawia wartość zmiennej a i wykonuje. Dzięki temu wyświetlone zostaną same zera. Okazuje się, że trzeba użyć specjalnego dodatkowego polecenia, które "sprowadza interpreter na ziemię" i powoduje normalne (w sensie powłoki Unix'a) podstawianie wartości (trzeba jednak użyć znaków ! zamiast %).

W sh oczywiście takich niuansów nie ma, a pętlę for można nawet zapisać sobie w jednej linii, bo koniec poleceń oznacza się średnikiem (brakuje mi tego w cmd). Niemniej jednak ten prosty w świecie Unix'a chwyt z liczeniem jest również możliwy w systemie Windows.

Na koniec zwrócę jeszcze uwagę, że w przypadku wykonywania pętli for w skrypcie, trzeba użyć *dwóch* znaków % przy zmiennej. W przypadku wpisywania ręcznie w interpreterze trzeba użyć jednej. Niuans ten, jak i powyższe spostrzeżenia moim zdaniem wystarczają do tego, żeby stwierdzić, że pisanie skryptów w cmd jest męczące. Pominąłem tutaj zupełnie wspomniany na początku PowerShell, gdyż jest to całkiem inny język i niekoniecznie jest obsługiwany przez starsze wersje systemu Windows (w XP trzeba go doinstalować).

 
1 , 2 , 3 , 4