Bash alias rejtély

Fórumok

Linuxmint.hu fórumon egyik fórumtársunknak megtelt a háttértár, és nem tudta miért.
Érdekelt a probléma, és csináltam egy szkripet, ami szépen lefut ha bemásolom a terminálba:

echo "elérési út: " ; read eu ; echo "mélység(1-10): " ; read mm ; for i in `seq ${mm:=5}` ; do eu=$(du -sh ${eu}/* 2>/dev/null | sort -h | tail -n1 | tee -a nagymappa | awk '{print $2}') ; done && cat nagymappa ; rm nagymappa

Ha viszont aliast csinálok hozzá a ~/.bashrc -be,

# Nagy mappák keresése
alias nmp='echo "elérési út: " ; read eu ; echo "mélység(1-10): " ; read mm ; for i in `seq ${mm:=5}` ; do eu=$(du -sh ${eu}/* 2>/dev/null | sort -h | tail -n1 | tee -a nagymappa | awk '{print $2}') ; done && cat nagymappa ; rm nagymappa'

Akkor a terminál újraindítása után hibaüzenetet kapok a promt megjelenése előtt:

bash: alias: }) ; done && cat nagymappa ; rm nagymappa: nem található
nff@sedre ~ $

Arra rájöttem, hogy az awk -val van probléma, és sikerült is megoldanom úgy, hogy cut -ra cseréltem, de bosszant, hogy sehogy nem bírok rájönni, mi a gond.
Sejtésem az, hogy talán az interaktív login mód hiányában lehet probléma, de nem értek annyira hozzá, hogy ezt átlássam.
Örülnék,ha valaki elmagyarázná, és érdekelne, hogy lehetne mégis aliasolni az awk-s szkriptet.

Hozzászólások

aposztrof-ot hasznalsz kivul es az awk-nal belul is. Az utobbi feloldja az elobbit

Próbáltam a külső aposztrofokat megduplázni, de így meg login előtt lefut.

bash: alias: elérési út: : nem található

mélység(1-10):
4
819G /mnt
819G /mnt/d45c8d68-77e6-4785-baff-a17b70175034
819G /mnt/d45c8d68-77e6-4785-baff-a17b70175034/backup
367G /mnt/d45c8d68-77e6-4785-baff-a17b70175034/backup/video
nff@sedre ~ $

Az se jó, ha rep jeleket (\) teszek a külső aposztrofok elé, akkor is hiba van.
Mi lehet ilyenkor a megoldás?

Így már tudom egymásba is ágyazni az aposztrofokat.

Nem hinném, mert ez nem hierarchikus. Csak bezárta az aposztrof által határolt stringet, hozzáfűzött egy literális aposztrofot, majd megnyitotta a string folytatását egy aposztroffal.

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

Az alábbi helyett:

awk '{print $2}'

valami ilyesmit írnék:

awk "{print \$2}"

A gond az volt - ahogy fentebb bazso kolléga írta -, hogy az awk scriptjét kezdő aposztrof valójában az alias elején lévőnek a záró párja volt. Az awk-nak csak egy stringet kell átadnod, nem muszáj azt aposztrofok között. Egyedül arra kell figyelni, hogy az a $ jel így ne a shellnek szóljon, hanem literálisként adódjon át az awk-nak.

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

Korábban pontosan ezt írtam be (illetve ezt akartam, de valamit elgépelhettem) és hibát adott. Ebből arra következtetem, hogy az awk kötelezően igényli az aposztrofot, és nem lehet helyette ". Most viszont sikerült hibátlanul bevinnem és MŰKÖDIK ! Ráadásul mindkét változatban, a $ escapelése nélkül is!

Hálás köszönet!!!

A $ escape-elését nem hagynám ki. Veszélyes következtetésekre lehet ám jutni kísérletezésekkel. Mutatok egy példát globbinggal:

mkdir proba
cd proba
rpm -qa kernel*
kernel-core-4.8.8-300.fc25.x86_64
kernel-headers-4.8.8-300.fc25.x86_64
kernel-modules-4.8.8-300.fc25.x86_64
kernel-devel-4.8.8-300.fc25.x86_64
kernel-4.8.8-300.fc25.x86_64

: >kerneltelenseg
rpm -qa kernel*

Ez utóbbi parancsra viszont már üres string a válasz, noha a kernel továbbra is a gépemen van. Annyi történt, hogy a bash nem talált az első esetben illeszkedést a globbingra, így a '*' karaktert literálisként adta át az rpm-nek. Az rpm pedig az összes kernel kezdetű feltelepített csomagot kilistázta.

A második esetben viszont létrehoztam egy kerneltelenseg nevű file-t. Ennek neve illeszkedett a globra, így aztán az rpm -qa kerneltelenseg parancs hajtódott végre, de ilyen nevű csomag nincs a gépemen, így visszatért üres kimenettel.

A helyes parancs például így nézett volna ki:

rpm -qa kernel\*

Szerk.:
arra következtetem, hogy az awk kötelezően igényli az aposztrofot

Az awk-nak sejtelme sincs arról, hogy ott az aposztrof. Az az idézőjel vagy aposztrof a shellnek szól, azt az awk nem kapja meg. Aposztrof esetén teljes elzárás van a stringen belül a shelltől, idézőjel esetén a helyettesítések maradnak, tehát csak részleges az elzárás. Ha egyiket sem írod, akkor viszont minden speciális karakter, globbing, brace expansion, helyettesítés, paraméterekre szeparálás, stb. értelmezésre kerül a shell által.

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

Igazad van, érdemes megtanulni megérteni pontosan az elméletét, akkor sok hibakereséstől kíméli meg magát az ember. Büki András könyvéből tanulok, meg a nemrég kiadott Szabad Szoftver Kompetencia Központ által kiadott könyvekből. Persze csak hobbista vagyok, de teszik nagyon a linux. Azt látom, hogy te nagyon profi vagy, ezért arra kérlek nézd át ezeket az aliasaimat, hogy nem csinálhatnak-e bajt.

# Mappa méreteket iratom ki vele
alias mm='echo "elérési út: " ; read eu ; du -sh ${eu}/* 2>/dev/null | sort -h'

# Lemez foglaltság kiíratása
alias lf='df -Thx tmpfs'

# Nagy mappák keresése
alias nmp='echo "elérési út: " ; read eu ; echo "mélység(1-10): " ; read mm ; for i in `seq ${mm:=5}` ; do eu=$(du -sh ${eu}/* 2>/dev/null | sort -h | tail -n1 | tee -a nagymappa | awk '\''{print $2}'\'') ; done && cat nagymappa ; rm nagymappa'

# Rejtett fájlok, mappák keresése
# alias rj='ls -aF | grep '\''^\.'\'' | xargs ls -ld'
alias rj='ls -AldF '\''.'\''*'

Néhol kicsit elbonyolítottad. Szerintem lehetne így is:

alias rj='ls --color=auto -AldF .*'

Ezen felül a read-nek van egy -p prompt kapcsolója, s akkor nem kell az echo elé. Nagymappa törlését rm -f nagymappa módon tenném, mert ha bármilyen hiba miatt nem jön létre a file, akkor a sima rm hibát dob, mondván, nincs mit törölnie, míg -f-fel úgy van vele, ha van mit törölni, letörli, ha nincs, akkor készen is vagyunk, tehát nem lesz hibaüzenet.

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

A --color=auto úgy látom nálam LinuxMinten elhagyható, ennyivel is rövidebb. Viszont az -A kapcsoló nálam ez esetben nem úgy működik, ahogy várnám önmagában sem a .* agumentummal. Elvileg a help szerint ez az -A kapcsoló arra van, hogy ne jelenítse meg a szülő, és az aktuális könyvtárat jelölő ., és .. könyvtárakat. De mégis. Azt tudom, hogy a kapcsolók felülbírálhatják, a sorban előttük lévőt, de hogy az argumentum is felülbírálja, ez nekem új. De inkább nem is az argumentum bírálja felül, hanem a takarás hiánya miatt a shell, Ha a .* argumentum nélkül adom ki, úgy működik, ahogy várom. (Tudom a számítógép a parancsaink és nem az óhajaink szerint működik)

Mindenkinek öszönöm a remek észrevételeket!
Örülök, hogy ilyen profikkal diskurálhatok, mint ti vagytok!

Nagyon jó, ez kell nekem. Bár, ha jól látom a két nem kívánt könyvtárat a .-t és a ..-t nem az -A kapcsoló , vagy nem csak az szűri ki, hanem a minta (is).
(ugyanazt az eredményt hozza, ha kiveszem az "A"-t)
A korábbiban pedig a éppen a minta miatt bírálódott felül az "-A", ha jól sejtem.

Ilyen sok utasításból álló parancs-sorozatra miért nem egy szkriptet hozol létre a ~/bin-ben? Sokkal kezelhetőbb, olvashatóbb, paraméterezhető...

Sorra fog kerülni, ez is, csak még egy kis rutint próbálok szerezni. Tudod, én nem informatikus vagyok, hanem egy roggyant bányász, és ezeket a programozásokat, az időskori teljes elhülyülés elleni küzdelem jegyében folytatom. Az asszony szerint nagyon mérsékelt sikerrel :-)