Atomgape kérése volt:
Na akkor most figyelj: kéne nekem egy script, amivel egy könyvtárban vagy könyvtárszerkezetben tömeges átnevezést tudok csinálni. Azaz mondjuk sok ilyen fájlnevem van:
Snoop Dogg - 01 - Bathtub -source.mp3
Snoop Dogg - 02 - Doggy Dogg World (feat. Tha Dogg Pound and The Dramatics) -source.mp3
(...)
Jó lenne, ha ki tudnám szedni a "-source" részt a végéről és a "Snoop Dogg - " részt az elejéről. Próbálkoztam, de a szóközök mindig kifogtak rajtam, így egyesével kell átneveznem.
Az egysoros megoldás erre a problémára szinte túl könnyű:
find ~ -name '* *' | while read F; do mv "$F" "$(echo $F | sed s/\-source//g)"; done
A gépházban eközben egy rakás fogaskerék kapcsolódik egymásba, miközben az is újfent kiderül, hogy a felhasználóbarát felülethez nem elsődlegesen fontos a grafikus interfész, valamint az átnevezés elvégzéséhez egyetlen animált gifet sem kellett megmozgatni. Ez sokak számára igen sajnálatos... hogy kicsit magyarázzak:
- A find paranccsal (ezzel kapcsolatban valszeg nem kell közvélemény-kutatás) fájlokat lehet keresni. A trükk a keresősztringben van, ahol nem egyszerűen '*'-ra, hanem a szóközzel elválasztott szavakra keresünk. A mohó mintaillesztés miatt ez fog illeszkedni mindenre, amiben van legalább egy szóköz. Ha olyanokra is akarunk illeszteni, ahol nincs szóköz, akkor ez egy új sor lesz, ezúttal '*' paraméterrel (!).
- A find parancs eredményét egy while ciklusba öntjük bele (a bash beépített függvénye), ahol a $F változóban találjuk az aktuális fájlnevet. Erre tehát elvégezzük az mv (átnevezés) parancsot: az eredeti fájlnevet olyanra cseréljük, ahol kivágtuk a "-source" karaktersort.
- A sed paraméterei között az első "s" a substitute (helyettesítés), aztán a megfelelő szintaxissal megadjuk, hogy mit mire (jelen esetben üres sztringre).
Mai rohanó, globalizálódó világunkban ;-) nem fogunk egy ennyire egy célra használható megoldással megelégedni: általánosítsuk tehát a problémát! Az első rögtön az, hogy a find-dal nem kereshetünk kétszer egymás után, hiszen akkor előfordulhat, hogy kétszer hozzábővítünk vagy elveszünk; egyetlen megoldás hogy egy sorban írjuk meg a szóközöket tartalmazó és nem tartalmazó kereső sort. Még jó, hogy a find-nak van -regex kapcsolója...
#!/bin/bash
Nem teszteltem, csak fejben bizonyítottam a működést... Ha csak két paramétert adok meg, akkor az aktuális könyvtárban és alatta keres; ha megadok, akkor abban.
# Bagoj ur tomeges fajl atnevezoje :)
# Hasznalat: massmv <könyvtár> mit mire
if [ $# = 3 ]; then
MYDIR=$1
MIT=$2
MIRE=$3
else
if [ $# = 2 ]; then
MYDIR="."
MIT=$1
MIRE=$2
else
echo "Hasznalat: $0 <könyvtár> mit mire"
exit 0
fi
fi
if [ -d "$MYDIR" ]; then
find "$MYDIR" -regex '.*' | while read F; do
if [ -f "$F" ]; then
NEWNAME=$(echo $F | sed "s/$MIT/$MIRE/g")
mv "$F" "$NEWNAME"
fi
done
else
echo "A megadott könyvtár nem megfelelő"
exit 0
fi
UPDATE: Kicsit a kezelésről, meg a működésről. Ugye a $# a parancssori paraméterek számát adja vissza, annak megfelelően beállítjuk a MYDIR, MIT és MIRE értékeket. Megnézzük, hogy a MYDIR valóban könyvtár-e, majd a könyvtáron belül a find-dal összegyűjtött fájlokon megyünk egyesével végig. A NEWNAME változóba tesszük be azt, amire cseréljük a fájlnevet, majd az mv paranccsal megcsináljuk az átnevezést.
A használatnál arra kell vigyázni, hogy escape-elni azért kell, tehát a szóközt, pontot, mindenféle zárójeleket bevezető visszaper-jellel kell megadni. Pl:
massmv /usr/zene/pop "\ " "_"
Ez a szóközöket aláhúzás-jelekre cseréli ki.