cp parancs: a fájlmappák helyes másolása a *nix-ben
Ez a cikk feltár néhány nem nyilvánvaló dolgot a használatával kapcsolatban helyettesítő karakterek másoláskor kétértelmű parancsviselkedés cp másoláskor, valamint olyan módszerek, amelyek lehetővé teszik nagyszámú fájl helyes másolását kihagyás vagy összeomlás nélkül.
Tegyük fel, hogy mindent át kell másolnunk a /source mappából a /target mappába.
Az első dolog, ami eszembe jut:
cp /source/* /target
Azonnal javítsuk ki ezt a parancsot:
cp -a /source/* /target
kulcs -a hozzáadja az összes attribútum, jog másolását és rekurziót. Ha nincs szükség a jogok pontos reprodukálására, elegendő egy kulcs -r.
Másolás után azt fogjuk tapasztalni, hogy nem minden fájlt másoltunk át – a ponttal kezdődő fájlok, például:
.profile
.local
.mc
és a hasonlók.
Miért történt ez?
Mivel a helyettesítő karaktereket a shell (bash tipikus esetben). Alapértelmezés szerint a bash figyelmen kívül hagy minden ponttal kezdődő fájlt, mivel rejtettként kezeli őket. Ennek a viselkedésnek a elkerülése érdekében magatartást kell változtatnunk bash parancs segítségével:
shopt -s dotglob
Annak érdekében, hogy ez a viselkedésváltozás az újraindítás után is fennmaradjon, létrehozhat egy wildcard.sh fájlt ezzel a paranccsal a mappában. /etc/profile.d (Talán a disztribúciójának más mappája van).
Ha pedig nincsenek fájlok a forráskönyvtárban, akkor a shell nem tud semmit sem helyettesíteni a csillag helyett, és a másolás is hibával meghiúsul. Vannak alternatívák ez ellen a helyzet ellen failglob и nullglob. Be kell állítanunk failglob, amely megakadályozza a parancs végrehajtását. nullglob nem fog működni, mivel egy olyan helyettesítő karakterláncot, amely nem talált egyezést, üres karakterláncsá alakítja (nulla hosszúságú), cp hibát fog okozni.
Ha azonban több ezer vagy több fájl van a mappában, akkor a helyettesítő karakterek megközelítését teljesen el kell hagyni. A tény az, hogy bash kibontja a helyettesítő karaktereket egy nagyon hosszú parancssorba, például:
cp -a /souce/a /source/b /source/c …… /target
A parancssor hosszának korlátja van, amit a paranccsal tudhatunk meg:
getconf ARG_MAX
Nézzük meg a parancssor maximális hosszát bájtban:
2097152
vagy:
xargs --show-limits
Valami ilyesmit kapunk:
….
Maximum length of command we could actually use: 2089314
….
Tehát teljesen nélkülözzük a helyettesítő karaktereket.
Csak írjunk
cp -a /source /target
És itt szembesülünk a viselkedés kétértelműségével cp. Ha a /target mappa nem létezik, akkor megkapjuk, amire szükségünk van.
Ha azonban létezik a célmappa, akkor a fájlok a /target/source mappába másolódnak.
A /target mappát nem mindig tudjuk előre törölni, mert tartalmazhat olyan fájlokat, amelyekre szükségünk van, és például az a célunk, hogy a /target fájlokat a /source fájlokkal egészítsük ki.
Ha a forrás- és a célmappa neve megegyezik, például a /source mappából a /home/source mappába másoltunk, akkor használhatjuk a következő parancsot:
cp -a /source /home
Másolás után a /home/source fájlokat a /source fájlokkal egészítik ki.
Ez egy logikai probléma: a célkönyvtárba felvehetünk fájlokat, ha a mappák neve azonos, de ha különböznek, akkor a forrásmappa a célkönyvtárba kerül. Hogyan másolhatunk fájlokat a /source-ból a /target-be cp használatával helyettesítő karakterek nélkül?
Ennek a káros korlátozásnak a megkerülésére egy nem nyilvánvaló megoldást használunk:
cp -a /source/. /target
Azok, akik ismerik a DOS-t és a Linuxot, már mindent megértettek: minden mappában 2 láthatatlan mappa található. és a „..”, amelyek pszeudo-mappák hivatkozásai az aktuális és magasabb könyvtárakra.
Másoláskor cp ellenőrzi a létezést, és megpróbálja létrehozni a /target/-t.
Létezik ilyen könyvtár, és ez a /target
A /source fájlokat a rendszer megfelelően másolja a /target mappába.
Tehát akassza fel egy vastag keretbe az emlékezetébe vagy a falra:
cp -a /source/. /target
Ennek a parancsnak a viselkedése egyértelmű. Minden hiba nélkül fog működni, függetlenül attól, hogy millió fájlja van, vagy nincs.
Álláspontja
Ha másolni kell minden fájlokat egyik mappából a másikba, nem használunk helyettesítő karaktereket, jobb, ha ezeket használjuk cp ponttal kombinálva a forrásmappa végén. Ezzel minden fájlt átmásol, beleértve a rejtetteket is, és nem fog meghibásodni több millió fájl esetén vagy egyáltalán nem.
utószó
vmspike parancsváltozatot javasolt hasonló eredménnyel: