[MEGOLDVA] Kis/nagy betű átalakítás

Fórumok

Sziasztok. Egy olyan problémába ütköztem, hogy egy filekezelőben saját scripttel meg akarom oldani, hogy a kijelölt fileokat át lehessen nevezni úgy, hogy minden szó első betűje nagy legyen, de a kiterjesztés maradjon kicsi. Ezt úgy oldottam meg először magában konzolban tesztelve egy scripttel, hogy minden kisbetűre alakítok (fumidname=), majd az extnum-ba beleírom hogy az utolsó ponttól a végéig hány karakter van -> vagyis a kiterjesztés hossza, vagy a sum változóba rakom az egész szöveg hosszát, és a new változóba rakom, hogy kiterjesztés nélkül milyen hosszú a szöveg. Utána a newstring-be rakom a kiterjesztés nélküli szöveget, amit a funewname változóba úgy rakom be, hogy minden szöveg kezdőbetűje nagy (ez a fajta sed felállás végzi a legjobban, mert nem zavarja meg sem a pont, sem az aláhúzás, sem az üres karakter), majd az ext változóba rakom a kiterjesztést, és a végén összefűzöm a kettőt, majd kiiratom. Elég fapados módszer, de működik. A probléma az, hogy bár ez terminál alatt jól működik, a kérdéses filekezelőben amit bash scripttel lehet programozni, mégis bad substitution szöveggel megáll, méghozzé a newstring=${fumidname:0:new} sornál, ami pont megadott karaktertől megadott karakterig írná ki -> ergo valamiért rosszul értelmezi.
Most vagy az lenne a megoldás, hogy erre esetleg más parancsot, megoldást találni, vagy a funewname= ..sed parancsos átalakításnál valahogy megadni a jelenlegi sed parancsnál, hogy ezt az átalakítást csak a legutolsó . -ig tegye, vagyis akkor jelentősen lerövidülni a script, mert nem kellene variálni a kiterjesztési manőverekkel. Ehhez viszont én már kevés vagyok.

 

#!/bin/bash
funame="1 - .VaLAmi_szIVAtTYú.TXt"
fumidname=$(echo "$funame" | sed 's/\([A-Z]\)/\L\1/g')
extnum=$(echo "$fumidname" | rev | cut -d. -f1 | rev | wc -c)
sum=$(echo "$fumidname" | wc -c)
new=$(expr $sum - $extnum)
newstring=${fumidname:0:new}
funewname=$(echo "$newstring" | sed 's/\([a-z]\)\([a-zA-Z0-9]*\)/\u\1\2/g')
ext=${fumidname:new:extnum}
funewname+=$ext
echo $funewname

Hozzászólások

Megoldás egy másik fórumról meg is jött:

fumidname-be berakja mindet lekicsinyÍtve, majd a newstringbe az utolsó pontig levő szöveget beilleszti, utána ezt a szöveget átalakítja, hogy minden szöveg első betűje nagy legyen, és megy a funewname változóba.

Utána az ext változóba rakja az utolsó pont utáni szöveget (ami már eleve kisbetű, hisz a legelején mindent kisbetűre tettünk). Ezeket a sztringeket összefűzi a funewname-ben (.-ot beszút a kettő közé), majd kiírja. Ilyen faramuci szöveggel is jól működik.

 

funame="1 - .VaLAmi sziVATtYú.TXt"
fumidname=$(echo "$funame" | sed 's/\([A-Z]\)/\L\1/g')
newstring=${fumidname%.*}
funewstring=$(echo "$newstring" | sed 's/\([a-z]\)\([a-zA-Z0-9]*\)/\u\1\2/g')
ext=${fumidname##*.}
funewname="$funewstring.$ext"
echo $funewname

Nem kell ide semmilyen változózás meg cut, simán egyetlen sed parancs, két cserével
echo "$funame" | sed -e 's/\([A-Z]\)/\L\1/g' -e 's/\([ ][a-z]\)/\U\1/g'

Ez azonban a kérdéses példánál szándékosan nem működik megfelelően, mivel a cut miatt feleslegesen teleszórtad a fájlneveket pont karakterekkel, én meg a pontról feltételezem a cserélési mintában, hogy azok fájlkiterjesztések, amelyeket nem akarsz nagybetűsíteni. A további jó hír, hogy az [a-z] megoldás mégis működik ékezetekkel, ez engem is meglep.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

Az általad leírt példa nekem nem működik. Kisbetűvé átalakítja, utána viszont már nem csinál semmit. De egy hozzászólással felette megírtam a megoldást. Az jóval egyszerűbb, mint amit én az eleján írtam, és rendben működik, nem zavarodik össze ha több pont van stb. Most azt használom már, és eddig egyszer sem tévedett, vagy nem kellett módosítanom. Az ékezeteket meg igen kezeli. Az elsők között volt, hogy azt leteszteltem még az elején mikor készítettem. Bár én nem használok ékezeteket, de idegen forrásból jövőknél előfordul.

Igen, írtam, hogy NEM működik, de szándékosan. A pont karaktereket elkerülendő. Te beletetted a névbe őket, hogy a cut paranccsal a pontok mentén mezőkre vágj, de mint írtam, az én megoldásom teljesen elkerüli a cut-ot, és a pontról feltételezi, hogy a közvetlenül azutáni karakter már a kiterjesztés, és nem kell nagybetűsíteni.

Ékezeteket én használok, igaz nem túl sűrűn, de nem is ritkán. 2022-ben nem kéne ennek gondot okozni, UTF8-ban tárolnak már a fájlrendszer, és a locale is rendszerint UTF8, aki meg őskőkori ISO-8859-akármi kódoláshoz ragaszkodik, az meg úgyis megszívja. Erre régen valóban kellett figyelni a 90-es és kora 2000-es években, hogy jajj, ékezeteket ha lehet nem, de most már nyugodtan lehetne. Nyilván van egy praktikus oldala is, ha tele rakja az ember a fájlneveket túl hülye karakterekkel, akkor azzal a launcher, fuzzy finder, egyéb programok nehezebben fognak boldogulni, nehezebb lesz rájuk hivatkozni, de tapasztalatom alapján néhány magyar, német, stb. ékezet, karakter az nem szokott gondot okozni ezen a téren sem. Egy japán karakternél már lehet problémás lenne, de olyat tényleg úgyse használok.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

Ha nem feltételezzük hogy az első karakter szám, akkor nem ártana azt is lecserélni:

$ echo "almafa alatt az ember.txt" | sed -e 's/\([A-Z]\)/\L\1/g' -e 's/\([ ][a-z]\)/\U\1/g' -e 's/\(^[a-z]\)/\U\1/g'
Almafa Alatt Az Ember.txt

Ugyanígy fel kell tételezni, hogy a szavakat mindig szóköz választja el.

Szóval kell még pár dolgot belehaluzni, hogy ez így jó legyen.

Nem hazudozás ez, de így van, ahogy írod. Nála ezek a fájlnevek mindig számmal kezdődnek. Aztán ha van is egy olyan rész, ahol nagybetűsíteni kéne, ott vagy pont vagy szóköz lesz neki benne. A _ karakter az benne van foglalva az [a-zA-Z] csoportba, azt azért nem nézzük. A pontnál szándékosan elvetettem, mert arról kiterjesztést feltételezek, és azt, hogy mégse használja feleslegesen a pontokat, ha egyszer nem kell a cut parancs, mivel a példám lényege, hogy ANÉLKÜL oldjuk meg. Így lényegében csak a szóközre kell figyelni.

Egyébként lehet úgy is csinálni, ahogy írod, az akkor is működik, ha nem számmal kezdődik neki. Szám, ilyen id vagy minek hívja viszont mindig van neki benne.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

"Nála ezek a fájlnevek mindig számmal kezdődnek" és "Szám, ilyen id vagy minek hívja viszont mindig van neki benne."

Ööö... ezt én nem láttam így leírva.

Aztán... a pont és a feltételezések. Csak egy példa: http://ftp.us.debian.org/debian/pool/main/z/zeroinstall-injector/

Változónevekből következtetek (lehet félreértem), nem ismerem a problémáját, nekem túlbonyolítottnak tűnik. Ezt a debian zeroinstall dolgot nem vágom, hogy jön ez a témához? Nem állítottam, hogy általánosságban minden fájl számmal kezdődik, hanem a szóban forgó problémára koncentráltam. De ha ez neked elég, legyen igazad, bevettél egy plusz sed mintát, ami a legelején lévő karaktert is lecseréli, ezt én nem érzem eget verő különbségnek, főleg, hogy én SZÁNDÉKOSAN nem törekedtem erre. Nyilván ez a megoldás tetszőlegesen bővíthető, ha valakinek nem jó, a sed parancs mögött annyi -e 's/minta/módosítás/g' paramétert ad meg, amennyit akar, kinek mire van szüksége.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

Van jópár rename parancssoros eszköz, amelyek hasznosak lehetnek (nem feltétlen most, hanem máskor is). Valamint ha esetleg szimpatizálsz a vim-mel, akkor a vim-renamer tetszeni fog :)

Total commander/csoportos atnevezes. :)

"Nem akkor van baj amikor nincs baj, hanem amikor van!"
Népi bölcsesség

Annyi, hogy ha Linux alatt kell, akkor a Total Commander-nek van egy Double Commander néven futó ukrán klónja, ami opensource és ingyenes, multiplatformos, általában minden disztró tárolójában ott van már doublecmd néven.

Hasonlót tud KRenamer is, meg sok más fájlkezelő (pl. Thunar). Én az ilyet Vifm-ben csinálom, kijelölt fájloknál átnevezéskor a vim-et nyitja meg, abban hajtom végre a tömeges átnevezést regexp-es cserével, majd mentés után kilépéskor átneveződnek a fájlok. Hasonlót tud a perl-rename nevű tool is, meg a vimv, qmv, és hasonlók, ezek mindegyike CLI. Van még egy hülye, lengyel nevű linuxos GUI program is rá, a szyszka (ejtsd: siska). Tudom, a neve nem bizalomgerjesztő, nem használtam még, de sokan dicsérik reddites szálakban.

A kolléga megoldása amúgy nem jó, mert az a regexp, amit megírt magának a shellscriptjében, az csak az ékezet nélküli alfanumerikus karaktereket fogja nagybetűsíteni, az ékezetes, és egyéb Unicode-karaktereket nem.

A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)

Köszi, de én kifejezetten CLI-s megoldásra éleződtem ki. Grafikus felület is egy tiling window manager (Bspwm). Meg itt most nem csoportos átnevezésről van szó, a példáid azokhoz jók. Azt már leprogramoztam, megnyitja a micro fileszerkesztőt, és ott átírom, majd mentéskor visszamenti a fileokat. Itt a kis betű, bnagy betűs móka volt a lényeg.

Beírom utolsó commentnek az lf programba létrehozott komplett parancsot, hátha valaki fog még ilyet használni:

cmd firstupcase %{{
    for f in $fx; do
        funame=`basename "$f"`
        fumidname=$(echo "$funame" | sed 's/\([A-Z]\)/\L\1/g')
        newstring=${fumidname%.*}
        funewstring=$(echo "$newstring" | sed 's/\([a-z]\)\([a-zA-Z0-9]*\)/\u\1\2/g')
        ext=${fumidname##*.}
        funewname="$funewstring.$ext"
        mv -n "$funame" "$funewname"
    done
}}