Összes fájl másolása alkönyvtárból

Újabb parancssoros megoldást szedtem össze. Már több (lent lesznek linkelve) tippet, trükköt is bemutattam. Ezeket közt van hasznos is, és kevésbé hasznos is. Érdemes a parancssor előnyeit is megismerni.

A legtöbb parancs amit bemutatok viszonylag hosszú, így érdemes azokat vagy alias-ban, vagy scriptben tárolni. Az első megoldás egy nagyon egyszerű, de hasznos, akár továbbfejleszthető egysoros, kétlépcsős parancs. Vagy (erről lesz szó majd!) egy más megoldást találni. Gondolatébresztőnek ezt olvassátok el!

A feladat: Az összes alkönyvtárban lévő fájlt másoljuk be a fő könyvtárba. Sok esetben kapunk, vagy töltünk le, esetleg tömörítvényeket bontunk ki, melyek sok alkönyvtárban lévő sok fájlokat tartalmaznak. Ha mi nem szeretnénk ezeket az alkönyvtárakból egyesével átmásolni egy másik könyvtárba a fájlokat, akkor kell valami megoldást keresnie.

Első megoldás, hogy a kedvenc fájlkezelőnkben a főkönyvtárra kiadjuk a keresés parancsot az összes olyan fájlra, amit szeretnénk mozgatni, majd a keresés eredményét egy panelba tesszük, és azt már másolhatjuk, mozgathatjuk. Ez szép, és egyszerű, meg is oldható pld. a krusder-rel, de a double commenderben ez csak félig megoldott, hiszen ha a panelbe (ott ablakba) küldjük a keresés eredményét, akkor másolni tudjuk, de mozgatni nem. Illetve vannak olyan fájlkezelők, amiben a keresés eredményeit nem tudjuk egy panelba megjeleníteni, és egyéb műveletet végezni velük. Így két megoldás van: vagy felrakjuk azt a fájlkezelőt ami tudja ezt, vagy kitalálunk egy parancssoros megoldást. Az első is jó, de ha ezt az utat követjük, akkor szépen gyűlnek a programok a gépen, hiszen mindig lesz egy olyan feladat, amit nem tud az egy, kettő, sok fájlkezelő amit eddig használtunk, megoldani.

A legtöbb ilyen furának tűnő feladatra már más is gondolt, és az interneten megoldást is tettek közzé. Ez jó, de azért van egyféle veszélye ennek. Nem minden válasz, megoldás korrekt, sok esetben hibás, vagy félig hibás megoldások is keringenek. Így mindig legyünk óvatosak, és éles futtatás előtt próbáljuk ki egy teszt környezetben. Illetve ami jobb, bár macerás: tanuljunk, és ismerjük meg az adott parancs felépítését.

A feladatra én ezt az egyszerű megoldást használom:

find . -mindepth 1 -type f -print -exec mv {} . \;

Ő lesz az, amin sok dolgot megtanulunk, de csak érintőlegesen. A fenti probléma megoldásra kétlépcsős parancs kell. Az első lépcsőben meg kell magyarázni a shell-nek, hogy legyen szíves az összes könyvtárban megkeresni az összes fájlt. Majd csináljon is vele valamit, azaz mozgassa át a fő könyvtárunkba. Olvasd el ezt, ha nem tudod, mi a shell!

Nem meglepő mód a keresést a find paranccsal végezzük, ami nagyon sokat tud, így gyakorlatilag az adott parancssori megoldás tovább is fejleszthető, igény szerint. Én abból indultam ki, hogy nekem az összes fájl kell, azaz nem csak az mp3-asokat, vagy a txt-t akarom, hanem az összeset. Így nem kell megadni egy konkrét fájltípust. A másik amit át kell gondolni, hogy ha van a főkönyvtárban is fájl, azokat nem bántsa, hiszen oda akarjuk a fájlokat másolni. Meg kell neki mondani, hogy a minimális könyvtár mélysége 1 legyen. A leírás szerint a mindepth 1 az összes fájlt feldolgozza, kivéve a kezdőpontokat. Így a kezdő, azaz a fő könyvtárban már nem fog tevékenykedni. Azt is szabályozni lehet, de itt nem kell a maxdepth-el, hogy milyen mélységig keressen. Mivel én nem egy statikus könyvtárat szeretnék használni, ahol megadom előre a kiinduló fő könyvtár nevét, így a „.” karakterrel elmondom a find-nek, hogy az adott könyvtárat, ahol indítva lesz a parancs, azt tekintse kiinduló pontnak. Fájlokat keressen, amit nyilvánvalóan a „type f” adja meg. Ez már megindítja azt a gondolatot, hogy ha fájlokat tud keresni, és ezt meg kell neki adni, akkor biztosan másokat is fel tud deríteni. Így univerzális eszköz, ami minden formációban keresni tud, ha azt a parancsot kapja. A „print” kapcsoló szintén egyértelmű, kiíratjuk az eredményt. Ez az a pont, ahol az első feladattal készen is vagyunk: megkerestetjük az alkönyvtárakban az összes fájlt. Ezt érdemes leellenőrizni, hiszen itt hamar kiderül, hogy valami nem olyanra sikerült, mint azt gondoltam. Egy ilyen hibakereső műveletet gyakran tegyünk meg, itt simán a parancssorba beírjuk, és ha kell javítsuk a részfeladatot ellátó szakaszt.

-exec mv {} . \;

Ezután már nem sok teendőnk van, csak a második felét is meg kell oldani a eladatnak, ami ténylegesen a cél feladat: másolni, mozgatni kell a megtalált fájlokat. Itt egy egyszerű, mindenki által használt parancs következik. Ha másolni akarunk, akkor cp, ha mozgatni, akkor mv parancsot használunk. Mivel ezek gyakorlatilag egyformák, így érdemes előbb a tesztelési időszakban a cp-vel kísérletezni. Így sokkal lassabb lesz, de nem törlődnek az eredeti, az alkönyvtárakban lévő fájlok. Tesztelésnél érdemes egy próbára szánt könyvtárszerkezetet használni, mert akkor nem veszhetnek el adataink. Gyakorlatilag a két parancs (mv, cp) egyszerű: mit, hova paramétereket vár el legalább. A find elég komoly program, nem csak keres, hanem tovább is tudja adni a keresés eredményét, és azzal jól szabályozható módon más parancsok is dolgozhatnak. Így nem a szokásos | (pipe) vagy egy fájlba kiírással oldjuk meg a továbbadást, hanem az -exec kapcsolóval. A man-ja elég terjedelmesen tárgyalja az exec részt, de mi csak egyszerűen átadjuk a kimenetet és semmi egyebet nem várunk el.

-exec mv {}

A "{}" karakterlánc helyébe az aktuális fájlnév kerül, ezt érdemes megjegyezni, ha több, a find által megkeresett fájlokkal akarunk bármikor dolgozni. Ez az mv (vagy a cp) első felét adja, azaz a mit másoljon, mozgasson. A hova pedig a „.” azaz az a könyvtár, amiben futtatjuk a parancsot. És vége: \; Ezt ne hagyd le, mert panaszkodni fog. Itt lehetséges más lezárás is, de én ezt választottam.

Ok, ha mindent jól tettél, akkor már készen is vagyunk. Vagy elmented script-nek, vagy alias-ként, vagy mindig begépeled, bemásolod.

Gondoljuk tovább a problémát! Bár általában a tervezési szakaszban sok olyan esetleges hiba jöhet elő, amit meg kell oldani, de ha kész van a „nagyon bonyolult és szuper” parancsunk, még kerülhetnek elő megoldandó feladatok.

Hm… mi lehet itt a hiba? Alapvetően semmi, de gondoljuk át, milyen esetekben okozhat ez adatvesztést, hibajeleket? Ha két egyforma fájlnév található, vagy egyes esetekben, ha az egyik alkönyvtárral megegyező nevű fájl kerül elő.

Kitérő: Bár nem kötelező, de érdemes minden esetben korrektül megadni a fájl kiterjesztését. Akár az ezegyszöveg, akár az ezegyszöveg.txt a szöveges fájl neve azt tudom használni. De ha éppen az adott könyvtárban van egy ezegyszöveg alkönyvtár és mellé akarunk létrehozni egy ilyen nevű fájlt, kiterjesztés nélkül, akkor panaszkodhat a rendszer. Ezt nem árt akkor sem kiemelten figyelni, ha akár a fájlnévből generáltatunk könyvtárnevet, vagy fordítva. Erre példa volt az egyik lentebb linkelt cikkben, ahol egy adott könyvtárt tömörítettünk, és abból generálódott le a tömörítvény neve.

Így kicsit tanulmányozni kell az mv leírását, és akkor találunk egy olyan kapcsolót, ami sorszámozni is tudja az azonos fájlneveket. Ez nem konkrétan erre a feladatra készült, hanem az mv-vel való adatmentésre, de itt is jól használható.

find . -mindepth 1 -type f -print -exec mv --backup=numbered {} . \;

Bár én az elsőt használom, mert amire nekem kell az is bőven megfelel, mert nincs azonos fájlnév.

Amit észrevettem, és nem csak itt igaz. Elvileg van mindegyik parancshoz man és help is, de érdemes az internetes man oldalakat is megkeresni, sokkal bővebbek, részletesebbek. Illetve a find-nél több példát is lehet találni a man oldalán.

Ennyi.