[Megoldva] A $REPLY értéke elromlik

Nézzük az alábbi scriptet:

#!/bin/bash

outext='mp4'

conv() {
    ffmpeg -i "$1" -an -vcodec copy "$2"
}

while read; do
    inext="`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"
    [ x"$inext" != x'mov' ] && continue
    outfile="${REPLY%.*}.$outext"
    conv "$REPLY" "$outfile"
done < <(ls -1)
exit 0

Azt most hagyjuk, hogy semmiféle ellenőrzés sincs benne, ideiglenesen kell. Ami számomra meglepő, hogy az alkönyvtárból csak néhány file-t konvertált. Kiírattam a $REPLY változót, az első file-nál jó volt a neve, utána viszont a filenevek első betűje hiányzott többnyire, de volt, hogy több is. A filenevek MVI_2193.MOV alakúak, tehát sem szóközök, sem ékezetes betűk nincsenek bennük. Azt tapasztaltam, hogy ha kikommentelem az ffmpeg-et, akkor jók lesznek a nevek. Olyan, mintha az ffmpeg elrondítaná az őt indító shell memóriáját. Ezt ugyan lehetetlennek gondolom, hiszen szerintem nem azonos process-ek.

Próbálkoztam process substitution helyett pipe-pal, illetve azzal, hogy a filelistát ideiglenes file-ba írom, majd az ideiglenes file-t irányítom a ciklusba, mindegyik megoldás esetén ugyanaz volt a hiba. A REPLY változót rögtön a ciklusmag elején átírtam egy REP változóba, de már itt sérült volt a file-ok neve. Próbálkoztam azzal is, hogy az ffmpeg-et subshellből indítottam, azaz kerek zárójelek közé tettem a paramétereivel együtt. Ez sem segített.

Ugyanakkor a

for REP in *; do ciklusmag done

alak működik jól.

Ez valami bug, vagy valamit nagyon benézek, nem tudok? Hogyan romolhat el egy változó látszólag ok nélkül?

Megoldás (köszönet érte Zahy mesternek):

Az ffmpeg az stdin-ről olvas olykor, így lenyúl néhány karaktert a read elől. Ezért le kell erről beszélni az ffmpeg-et:

ffmpeg -i "$1" -an -vcodec copy "$2" </dev/null &>/dev/null

Vagy lehet így is:

ffmpeg -nostdin -i "$1" -an -vcodec copy "$2" &>/dev/null

Hozzászólások

Hát ez elég rejtélyesnek tűnik.

Mi lenne ha egy *nagyon* rövid időre elfelejtkeznél arról, hogy a read a REPLY-ba olvas, és adnál oda egy saját változót - meg nyilván a kód egyéb részében is kicserélnéd a $REPLY-t. Ezt sem igazán érteném ha működne, de akkor pl. simán arra lehet fogni, hogy van még valahol egy olyan shell-konstrukció, ami szintén a REPLY-t buzerálja. A másik, hogy mit látsz egy "bash -v -x scripted" futtatásakor? (Ha nem használnál annyi bash-specifikus vackot, javasolnám a pdksh-val vagy a ksh93-mal egy ellenteszt futtatását, de a <<< és a <<(ls) részt is át kéne írni. OK, ez a kettő csak a bash-specifikus.)

Hirtelen jött ötlet, valószínűleg hülyeség, de mit lehet tudni: a szóban forgó ffmpeg csak binárisként van jelen a rendszereden vagy van hozzá valami alias/bash függvény? (lásd még paraméter nélküli set kimenete!)

Aki tudja, csinálja, aki nem tudja, tanítja... Hm... igazgatónak talán még jó lennék. :)

És a param nélküli set?
(kb. 0 az esélye, de ilyen hülye hibánál...)

A másik, hogy a
inext="`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"
szerinted mit kell, hogy csináljon?

Mert ez valamit levág a REPLY változóból, ha jól emlékszem a bash lelkivilágára, de pl. a csillaggal nem tudom, mit kezd.

Aki tudja, csinálja, aki nem tudja, tanítja... Hm... igazgatónak talán még jó lennék. :)

Azt elárulod, hogy az inext előállításánál miért csinálod azt, hogy az idézőjelet bezárod a <<< után azonnal, aztán a REPLY már nincs idézőjelben, aztán a végét megint idézőjelbe teszed?

Elárulom helyette.
Az, amit Te bezárásnak látsz, egy újabb nyitás, mert kimenet változóba irányításán belül van (``).
Ha ehelyett:
"`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"

Ez lenne:
"$(tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}")"

Jobban látható lenne? /Hint: zárójelen belüli és -kívüli idézőjelek/
--
PtY - www.onlinedemo.hu

Megtennéd, hogy ezt

inext="`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"

másként írod?
a) verzió:

inext="`tr '[:upper:]' '[:lower:]' <<<\"${REPLY##*.}\"`"

b) verzió:

inext="`echo \"${REPLY##*.}\" | tr '[:upper:]' '[:lower:]'`"

És nyilván az érdekel, hogy valamelyiktől megjavult-e.

Ezt most nem értem, én idézőjelről beszélek, te zárójelről. Fenti két példád meg köszönőviszonyban sincsenek egymással. Az első az előbb lefuttatja a korte nevű parancsot oly módon, hogy amíg fut, van neki egy extra környezeti változója az ALMA, alma értékkel. Majd lefuttatja a szilva parancsot. A második pedig az ALMA változónak értékül adja az alma korte és szilva szavakat, az első kettő közé egy szóköz kerül, a második és a harmadik közé pedig egy soremelés. Szóval nem értem.

idézőjelet akartam írni, nem zárójelet.

A példa meg arra szól, mi lesz, ha elhagyod a zárójelet. "Ha egyszer az egész idézőjelben van, akkor azon belül a $REPLY is idézőjelen belül van."

A $REPLY nincs idézőjelben, mert a kimenet van idézőjelek közt, nem az, amit a REPLY ad vissza. Ha abban van egy sortörés pl., az nagy cumi tud lenni idézőjel nélkül.

pl.
KIMENET="`A=$(echo -e "alma\nkorte") && mkdir "$A"`"

és ugyanezt próbáld ki egy másik könyvtárban belső idézőjelek nélkül, majd vesd össze az eredményt. Elég, ha a "$A"-ról veszed le :)

--
PtY - www.onlinedemo.hu

Ocsmány, és a javaslatoddal nincs is semmi baj, legyen úgy.
Én erre reagáltam:
"Ha egyszer az egész idézőjelben van, akkor azon belül a $REPLY is idézőjelen belül van."
Ez így konkrétan nem igaz, mert a `-n belül nincs idézőjelben idézőjel.

Mint ahogyan az

echo "$(echo "$(echo "$(echo "$(echo "izé")")")")"

is teljesen jó :D
--
PtY - www.onlinedemo.hu

Én is meresztettem a szemem egy darabig, h mi a tököm ez.
Pont emiatt szoktam rá a `` helyett a $() használatára, bár nem ekvivalens a kettő. az előbbi példám pl. ``-k használatával a második ` értelmezésekor a bash-nak azonnal végrehajtási kényszere van az `echo "`-n, és be is okádja a hibát. ``-k esetén nem tudja kezelni a nyitó-záró párokat úgy, mint $() esetén.
Lehet, hogy el lehet escape-elni, azt nem próbáltam. Igen, a doksit sem olvastam végig :)
Nem, nem az ffmpeg doksijáról beszélek (bár, azt sem olvastam végig) :D
--
PtY - www.onlinedemo.hu

Szerintem a backtick miatt nem az a sorrend. Lehet, hogy tévedek. Ha ezt írom:


inext="$(tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}")"

hogy a $( )-en belül vannak idézőjel párok, s a helyettesítést öleli körül a külső idézőjel-pár? Ezt feltételeztem a backtick esetében is.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Egy biztos: ubuntun, ext3 fájlrendszeren csak annyi hibát kapok, hogy az ffmpeg deprecated.
A fájlnevekkel nincs gondja.
Viszont az upper case-ből és a nevekből arra tippelek, ez valami nem linuxos fájlrendszerről jön.
Biztosan nincs valami szemét a fájlnevekben? Mondjuk a végükön?

Aki tudja, csinálja, aki nem tudja, tanítja... Hm... igazgatónak talán még jó lennék. :)

Igen, kipróbáltam, működik. Az RTFM-re azért csak részben adok igazat. Egyrészt, majdnem 1500 sor, másrészt ahhoz előbb rá kellett jönni, hogy a hiba az ffmpeg által történő stdin legelészéséből fakad. :) Viszont, ha ezt tudjuk, akkor a shellel is befoghatjuk az ffmpeg éhes száját, másfelől innen jutott eszembe, hátha van erre kapcsoló. És van, és még működik is:

       -stdin
           Enable interaction on standard input. On by default unless standard
           input is used as an input. To explicitly disable interaction you
           need to specify "-nostdin".

           Disabling interaction on standard input is useful, for example, if
           ffmpeg is in the background process group. Roughly the same result
           can be achieved with "ffmpeg ... < /dev/null" but it requires a
           shell.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az enyimnek se a manuálja, se a binárisa szerint nincsen ilyen opciója.

$ ffmpeg -nostdin
ffmpeg version 0.7.8, Copyright (c) 2000-2011 the FFmpeg developers
built on Dec 3 2011 01:25:21 with gcc 4.2.2 20070831 prerelease [FreeBSD]
configuration: --prefix=/usr/local --mandir=/usr/local/man --enable-shared --enable-gpl --enable-postproc --enable-avfilter --enable-pthreads --enable-x11grab --enable-memalign-hack --enable-runtime-cpudetect --cc=cc --extra-cflags='-I/usr/local/include/vorbis -I/usr/local/include' --extra-ldflags='-L/usr/local/lib ' --extra-libs=-pthread --disable-debug --disable-sse --disable-mmx --disable-libaacplus --disable-indev=alsa --disable-outdev=alsa --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-libcelt --disable-libdirac --disable-libfaac --enable-libfreetype --enable-frei0r --disable-libgsm --disable-libmp3lame --enable-libopencv --disable-libopenjpeg --disable-librtmp --enable-libschroedinger --disable-ffplay --disable-libspeex --enable-libtheora --disable-vaapi --disable-vdpau --disable-libvo-aacenc --disable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxvid
libavutil 50. 43. 0 / 50. 43. 0
libavcodec 52.123. 0 / 52.123. 0
libavformat 52.111. 0 / 52.111. 0
libavdevice 52. 5. 0 / 52. 5. 0
libavfilter 1. 80. 0 / 1. 80. 0
libswscale 0. 14. 1 / 0. 14. 1
libpostproc 51. 2. 0 / 51. 2. 0
ffmpeg: unrecognized option 'nostdin'

(Tudom, frissíteni fogom hamarosan, csak jó lenne arra a verzióra, amelyik jól működik.

+++
Ne frissítsd! Az az ffmpeg nem az az ffmpeg!

$ ffmpeg --nostdin
ffmpeg version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, Copyright (c) 2000-2013 the Libav developers
built on Apr 2 2013 17:00:59 with gcc 4.6.3
*** THIS PROGRAM IS DEPRECATED ***
This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.
Missing argument for option '-nostdin'

$ avconv --nostdin
avconv version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, Copyright (c) 2000-2013 the Libav developers
built on Apr 2 2013 17:00:59 with gcc 4.6.3
Missing argument for option '-nostdin'

De ezt mondjuk nem értem:
$ ls -la $(which ffmpeg)
-rwxr-xr-x 1 root root 100816 ápr 2 19:03 /usr/bin/ffmpeg

$ ls -la $(which avconv)
-rwxr-xr-x 1 root root 109008 ápr 2 19:03 /usr/bin/avconv

Nem symlink, külön bináris, amibe belefordították a DEPRECATED üzenetet... Besenyő István erre csak egyet kérdezne...

--
PtY - www.onlinedemo.hu

Jól érted. Virtuális ffmpeg. Olyan, mintha az lenne, de mégsem.
Nem tudom, milyen disztrót használsz, de az abban lévő ffmpeg, és az Ubork@ alatti nem ugyanaz :)

Tudod: exim, sendmail, postfix, qmail, stb... mindegyikben van /usr/bin/sendmail bináris. Mégsem ugyanazok ők :)
--
PtY - www.onlinedemo.hu

Fedora 19-et használok.

Arról van szó, hogy az egyes disztribútorok más opciókkal fordítják? Ez valahol természetes, ki-ki a saját elveit, céljait szem előtt tartva cselekszik. Abból, hogy az rpmfusion-free-updates repóból van, arra következtetek, hogy licencelési okokból tették oda. Például már az mp3 is ilyen, és még rengeteg formátumot ismer az ffmpeg, amelynek a licence talán nem egészen kompatibilis a Fedora project által megfogalmazott kívánalmakkal.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

WTF. Épp javasolni akartam, h futtasd már úgy, hogy minden megvan, de a ciklusmagban csak a REPLY kiíratása van. Másik teszt, ne kikommentezd az ffmpeg-et, hanem helyette legyen echo ffmpeg ..., azaz az látszódjon, hogy tényleg az ffmpeg rontja-e el, vagy az, hogy ott lefut egy tetszőleges parancs.


ls -1
MVI_2193.MOV
MVI_2194.MOV
MVI_2195.MOV
MVI_2196.MOV
MVI_2197.MOV
MVI_2198.MOV
MVI_2199.MOV
MVI_2200.MOV
MVI_2201.MOV
MVI_2202.MOV


REPLY='MVI_2193.MOV'            inext='mov'
REPLY='VI_2194.MOV'             inext='mov'
REPLY='MVI_2195.MOV'            inext='mov'
REPLY='VI_2196.MOV'             inext='mov'
REPLY='MVI_2197.MOV'            inext='mov'
REPLY='VI_2198.MOV'             inext='mov'
REPLY='MVI_2199.MOV'            inext='mov'
REPLY='VI_2200.MOV'             inext='mov'
REPLY='MVI_2201.MOV'            inext='mov'
REPLY='VI_2202.MOV'             inext='mov'

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Sajnos, csak az látszik, a read hülyeséget olvas. Részlet:


+ outext=mp4
++ ls -1
+ read
+ echo -ne 'REPLY='\''MVI_2193.MOV'\''\t\t'
REPLY='MVI_2193.MOV'            ++ tr '[:upper:]' '[:lower:]'
+ inext=mov
+ echo 'inext='\''mov'\'''
inext='mov'
+ '[' xmov '!=' xmov ']'
+ outfile=MVI_2193.mp4
+ conv MVI_2193.MOV MVI_2193.mp4
+ ffmpeg -i MVI_2193.MOV -an -vcodec copy MVI_2193.mp4
+ read
+ echo -ne 'REPLY='\''VI_2194.MOV'\''\t\t'
REPLY='VI_2194.MOV'             ++ tr '[:upper:]' '[:lower:]'

+ inext=mov
+ echo 'inext='\''mov'\'''
inext='mov'
+ '[' xmov '!=' xmov ']'
+ outfile=VI_2194.mp4
+ conv VI_2194.MOV VI_2194.mp4
+ ffmpeg -i VI_2194.MOV -an -vcodec copy VI_2194.mp4
+ read

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Annak utána tudnál esetleg nézni, hogy ez melyik ffmpeg? (Mer' ugye mintha az originál - Niedermayer-féle? - le lett volna nyúlva, és most van ffmpeg meg valami avcodec vagy mi a tüdő - sajnos nem tudom melyik a melyik. Jó lenne tudni, hogy melyik az, amelyik még értelmes paraméterezés esetén is fölöslegesen olvasgat a user termináljáról. Hm, szerintem ezt a verziót is az NSA-supportálja.)


ffmpeg -version
ffmpeg version 1.2.2
built on Aug  4 2013 08:24:19 with gcc 4.8.1 (GCC) 20130603 (Red Hat 4.8.1-1)
configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic' --enable-bzlib --disable-crystalhd --enable-frei0r --enable-gnutls --enable-libass --enable-libcelt --enable-libdc1394 --disable-indev=jack --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-openal --enable-libopencv --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libvpx --enable-libx264 --enable-libxvid --enable-x11grab --enable-avfilter --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-runtime-cpudetect
libavutil      52. 18.100 / 52. 18.100
libavcodec     54. 92.100 / 54. 92.100
libavformat    54. 63.104 / 54. 63.104
libavdevice    54.  3.103 / 54.  3.103
libavfilter     3. 42.103 /  3. 42.103
libswscale      2.  2.100 /  2.  2.100
libswresample   0. 17.102 /  0. 17.102
libpostproc    52.  2.100 / 52.  2.100

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Végül ez lett belőle:

#!/bin/bash

out_ext='mp4'

conv() {
    echo "Converting $1 to $2"
    ffmpeg -nostdin -i "$1" -an -vcodec copy "$2" &>/dev/null
}

while read; do
    in_ext="`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"
    [ -f "$REPLY" -a x"$in_ext" = x'mov' ] || continue
    outfile="${REPLY%.*}.$out_ext"
    conv "$REPLY" "$outfile"
done < <(ls -1)
exit 0

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az x-et azóta használom, amióta csúnyán megszívtam, hogy a helyettesítésre kerülő string a test számára operátorként is értelmezhető volt. Talán (, vagy valami hasonló dolog. Úgy vagyok vele, nincs kedvem gondolkodni, a memóriában az a 2 byte elfér.

Használhatok ott idézőjelet, de string konstansoknál aposztrofot szoktam, így nem kell escape-elnem, ha pl. $-t tartalmaz.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az alairasodbol is latom, hogy szereted a tr-t a kis-nagybetu konverziora, de ujfent javaslom, hogy sporolj meg egy processzt (de legalabbis tanuld meg, hogy van egy ilyen lehetoseg is :-P ):

in_ext="`tr '[:upper:]' '[:lower:]' <<<"${REPLY##*.}"`"

a fentit erre cserelve, ugyanaz lesz az eredmeny, csak epp a shell beepitett funkciojat hasznalod, tehat gyorsabb:

typeset -l in_ext="${REPLY##*.}"

(A typeset az - szigoruan bash-ban - irhato declare-nek is, de az elozo forma hordozhatobb :-) a ksh iranyaba. Nyilvan letezik parja is, typeset -u, azaz LowerCase vagy UpperCase konverzio tortenik az adott valtozokon ertekadaskor.)

Nem, typeset-et barmikor allithatok. Akar azt is megtehetem, hogy amig szukseges, addig egy jellemzot beallitok, aztan amikor nem erdekes, akkor leszedek a valtozorol:

valtozo=alma
typeset -u valtozo
echo $valtozo # -> ALMA
typeset +u valtozo
typeset -l valtozo
echo $valtozo # -> alma
typeset +l valtozo
typeset -i valtozo # ugyan az alma nem szam, de megmaradhat
valtozo=korte # ez viszont mar hibat eredmenyez, innentol nem kaphat csak egesz szam erteket
korte=3
valtozo=korte # ez ekvivalens valtozo=$korte -vel
valtozo=szilva # megint hiba
typeset +i valtozo
valtozo=szilva # most mar mehet

De mondjuk ez eleg extrem pelda. Viszont a kis/nagybetusites kifejezetten kenyelmes.
Szerk: a SIG-es reszt nem ertem (hacsak nem locsemege SIG-jerol van szo)

Öööö, izé...

$ locale
LANG=hu_HU.UTF-8
LANGUAGE=
LC_CTYPE="hu_HU.UTF-8"
LC_NUMERIC="hu_HU.UTF-8"
LC_TIME="hu_HU.UTF-8"
LC_COLLATE="hu_HU.UTF-8"
LC_MONETARY="hu_HU.UTF-8"
LC_MESSAGES="hu_HU.UTF-8"
LC_PAPER="hu_HU.UTF-8"
LC_NAME="hu_HU.UTF-8"
LC_ADDRESS="hu_HU.UTF-8"
LC_TELEPHONE="hu_HU.UTF-8"
LC_MEASUREMENT="hu_HU.UTF-8"
LC_IDENTIFICATION="hu_HU.UTF-8"
LC_ALL=

$ echo "méghogy működik... lóf@szt" | tr '[:lower:]' '[:upper:]'
MéGHOGY MűKöDIK... LóF@SZT

:D
--
PtY - www.onlinedemo.hu

Nem kéne valami normális oprendszert használni?

$ env LC_ALL=hu_HU.UTF-8 ksh
$ echo öt szép szűzlány őrült írót nyúz
öt szép szűzlány őrült írót nyúz
$ echo öt szép szűzlány őrült írót nyúz | tr '[:lower:]' '[:upper:]'
ÖT SZÉP SZŰZLÁNY ŐRÜLT ÍRÓT NYÚZ
$ uname -a
FreeBSD mikozodhozza.Zahemszky.HU 9.2-RELEASE FreeBSD 9.2-RELEASE #0 r255898: Thu Sep 26 22:50:31 UTC 2013 root@bake.isc.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64
$

(Mindentől függetlenül valami olasmi is rémlik, hogy ezeket a tr paramétereket még egy szögleteszárójelbe kellene tenni:

$ echo öt szép szűzlány őrült írót nyúz | tr '[[:lower:]]' '[[:upper:]]'
ÖT SZÉP SZŰZLÁNY ŐRÜLT ÍRÓT NYÚZ
$

ami egyébként rontani szerintem nem tud a helyzeteden.)

A tr-nek a szögletes zárójelek duplázása nélkül kéne tudnia, amit itt várunk, mert ez nem RE, csak karlista, de a tr maga bénázik.

OS most felmentve, mert pl.:


$ LANG=C awk '/^[[:lower:]]+$/' <<< "áéíöőúű"
$ LANG=hu_HU.UTF-8 awk '/^[[:lower:]]+$/' <<< "áéíöőúű"
áéíöőúű

Bakker, nem kéne odafigyelés nélkül posztolgatnom, mert hülyeség lesz belőle.

a) a typeset -u és -l magától nem konvertál, csak értékadáskor (folyománya, ha konvertálni akarok, akkor a konvertáláshoz kell mondjuk egy valtozo="$valtozo" jellegű "értelmetlen/felesleges" értékadás)
b) ha egy változó integer tipusú (typeset -i), és értékül valami olyat kap, ami nem egész szám, és még csak nem is egész szám értékkel bíró változó neve, akkor nem hibaüzenetet ad, csak simán 0-t ad értékül.

A többi stimmel.

apt-get install ksh93 && man ksh93 /typeset -F
Ja, fedora, akkor s/apt-get/yum/
:-D
Ui: sajnos jelenleg a pdksh ezt még nem tudja, de elképzelhető, hogy a MirBSD-féle mksh már szintén. De mióta David Korn sajár Korn-shellje is szabadon elérhető, azóta ezek az utánérzések azért nem olyan ütemben fejlődnek, mint régen :-)