A Bash fájlok elnevezési szokásai nagyon gazdagok, és könnyű létrehozni egy szkriptet vagy egyvonalasat, amely helytelenül elemzi a fájlneveket. Tanulja meg a fájlnevek helyes elemzését, és ezzel biztosítsa, hogy a parancsfájlok megfelelően működjenek!
A Bash fájlnevek helyes elemzésével kapcsolatos probléma
Ha egy ideje használja a Bash szoftvert, és gazdag Bash nyelven írt szkripteket, akkor valószínűleg néhány fájlnév elemzési problémába ütközik. Vessünk egy pillantást arra, hogy mi romolhat el:
touch 'a > b'
Itt létrehoztunk egy fájlt, amelynek tényleges CR
(kocsi vissza) az enter nyomva tartásával vezetjük be a a
. A Bash fájlok elnevezési szokásai nagyon gazdagok, és bár bizonyos szempontból hűvös, használhatunk ilyen karaktereket egy fájlnévben, de nézzük meg, hogyan jár ez a fájl, amikor megpróbálunk néhány műveletet végrehajtani rajta:
ls | xargs rm
Ez nem sikerült. xargs
innen veszi a bemenetet ls
(a |
cső), és adja át rm
, de közben valami elromlott!
Ami rosszul történt, az a kimenet ls
szó szerint veszi xargs
és az „enter” (CR
– Carriage Return) a fájlnéven belül látja xargs
mint tényleges befejező karakter, nem a CR
hogy továbbadják rm
ahogy lennie kell.
Példázzuk ezt más módon:
ls | xargs -I{} echo '{}|'
Tiszta: xargs
a bemenetet két külön sorként dolgozza fel, az eredeti fájlnevet kettéválasztva! Még akkor is, ha egyesek kijavítanánk az űrproblémákat divatos elemzés sed segítségével, hamarosan más kérdésekbe ütköznénk, amikor elkezdünk más speciális karaktereket használni, például szóközöket, visszavonásokat, idézőjeleket és egyebeket!
touch 'a b' touch 'a b' touch 'ab' touch 'a"b' touch "a'b" ls
Még akkor is, ha gyakorlott Bash-fejlesztő vagy, megborzonghatsz az ilyen fájlnevek láttán, mivel nagyon összetett lenne a leggyakoribb Bash-eszközök számára, ha ezeket a fájlokat helyesen elemzik. Mindenféle karakterlánc-módosítást meg kell tennie, hogy ez működjön. Vagyis, hacsak nincs meg a titkos recept.
Mielőtt belemerülnénk, van még egy dolog – kötelező tudnivaló -, amelybe belefuthat elemzés közben ls
Kimenet. Ha színkódolást használ a könyvtárlistákhoz, amely alapértelmezés szerint engedélyezve van az Ubuntuban, könnyen futtatható egy másik ls
elemzési kérdések.
Ezek valójában nem a fájlok megnevezésével, hanem a fájlok kimenetként történő megjelenítésével kapcsolatosak ls
. Az ls
A kimenet hex kódokat tartalmaz, amelyek a terminálon használandó színt képviselik.
Annak elkerülése érdekében, hogy ezekbe belefusson, egyszerűen használja --color=never
opcióként ls
:ls --color=never
.
A Mint 20-ban (egy nagyszerű Ubuntu származékos operációs rendszer) ez a probléma megoldottnak tűnik, bár a probléma továbbra is fennállhat az Ubuntu számos más vagy régebbi verziójában stb. Ezt a kérdést a 2020-as augusztus közepén láttam az Ubuntu-ban.
Még akkor is, ha nem használ színkódolást a könyvtárlistáihoz, lehetséges, hogy a szkript más rendszereken is fut, amelyek nem az Ön tulajdonában vagy kezelésében vannak. Ilyen esetben ezt a beállítást arra is használni kívánja, hogy megakadályozza az ilyen gép felhasználói futtatását a leírt kérdésben.
Visszatérve a titkos receptünkhöz, nézzük meg, hogyan tudunk megbizonyosodni arról, hogy a Bash fájlnevekben nem lesz probléma a speciális karakterekkel. A rendelkezésre álló megoldás elkerüli az összes felhasználását ls
, amelyet jó lenne elkerülni általában, ezért a színkódolási kérdések sem alkalmazhatók.
Még mindig vannak olyan helyek, ahol ls
az elemzés gyors és praktikus, de mindig bonyolult és valószínűleg „piszkos”, amint a speciális karaktereket bevezetik – nem beszélve a bizonytalanságról (speciális karakterek használhatók mindenféle probléma bemutatására).
A titkos recept: NULL felmondás
A Bash eszköz fejlesztői sok évvel korábban felismerték ugyanezt a problémát, és a következőket nyújtották nekünk: NULL
felmondás!
Mi a NULL
felmondást kérsz? Fontolja meg, hogy a fenti példákban CR
(vagy szó szerint belép) volt a fő befejező karakter.
Azt is láttuk, hogy a speciális karakterek, például az idézőjelek, a szóközök és a perjelek felhasználhatók-e a fájlnevekben, annak ellenére, hogy különleges funkcióik vannak, ha más Bash-szöveg elemző és módosító eszközökről van szó, mint például a sed. Most hasonlítsa össze ezt a -0
opció xargs, tól től man xargs
:
-0, –nem A beviteli elemeket egy üres karakter fejezi be a szóköz helyett, és az idézőjelek és a visszavágás nem különlegesek (minden karakter szó szerint értendő). Letiltja a fájl karaktersorozatának végét, amelyet minden más argumentumhoz hasonlóan kezelünk. Hasznos, ha a beviteli elemek lehetnek szóközök, idézőjelek vagy visszavágás. A GNU find -print0 opció ehhez az üzemmódhoz megfelelő bemenetet állít elő.
És a -print0
opció find
, tól től man find
:
-fprint0 fájl Igaz; nyomtassa ki a teljes fájlnevet a szabványos kimenetre, majd egy null karaktert (a -print által használt újsoros karakter helyett). Ez lehetővé teszi, hogy az új sorokat vagy más típusú szóközt tartalmazó fájlneveket helyesen értelmezzék a keresési kimenetet feldolgozó programok. Ez az opció megfelel az xargs -0 opciójának.
Az Igaz; itt azt jelenti Ha az opció meg van adva, akkor a következő igaz;. Szintén érdekes az ugyanazon kézikönyv oldalon máshol megadott két egyértelmű figyelmeztetés:
- Ha a keresés kimenetét egy másik programba irányítja, és a lehető legkevesebb lehetőség van arra, hogy a keresett fájlok új sort tartalmazzanak, akkor komolyan fontolja meg a -print0 opció használatát a -print helyett. A szokatlan karakterek kezeléséről a SZOKOTlan FÁJLNÉVEK részben olvashat.
- Ha a keresést szkriptben használja, vagy olyan helyzetben, ahol az egyező fájloknak tetszőleges nevük lehet, akkor fontolóra kell vennie a -print0 helyett -print.
Ezek az egyértelmű figyelmeztetések arra emlékeztetnek minket, hogy a bash fájlnevek elemzése trükkös üzlet lehet és ez is. A megfelelő opciókkal azonban find
, mégpedig -print0
, és xargs
, mégpedig -0
, minden fájlneveket tartalmazó speciális karakterünket helyesen lehet elemezni:
ls find . -name 'a*' -print0 find . -name 'a*' -print0 | xargs -0 ls find . -name 'a*' -print0 | xargs -0 rm
Először ellenőrizzük a könyvtárlistánkat. Minden speciális karaktereket tartalmazó fájlnevünk ott van. Ezután csinálunk egy egyszerű find ... -print0
hogy lássa a kimenetet. Megjegyezzük, hogy a húrok NULL
megszűnt (a NULL
vagy