-exec opciójának megértése, hogy folyamatosan a

find . -name "FILENAME" -exec rm {} \; 

főleg azért, mert nem látom, hogy pontosan hogyan működik a -exec rész. Mit jelentenek a zárójelek, a hátsó perjel és a pontosvessző? Vannak más felhasználási esetek is ez a szintaxis?

Megjegyzések

  • @Philippos: Látom az értelmét. Kérjük, ne feledje, hogy a man oldalak referenciák, azaz hasznosak azok számára az ügy megértésével keresse meg a szintaxist. Ha valaki új a témában, gyakran rejtélyes és formális, hogy hasznos legyen. Meg fogja találni, hogy az elfogadott válasz körülbelül tízszer olyan hosszú, mint a man oldal bejegyzése, és hogy ‘ ok valamilyen okból.
  • Még a régi POSIX man oldalon is olvasható Egy segédprogram_neve vagy argumentuma csak a két karaktert tartalmazza ” {} ” d az aktuális útnév vel, ami számomra elégségesnek tűnik. Ezenkívül a -exec rm {} \; példával is rendelkezik, akárcsak a kérdésében. Napjaimban alig volt más erőforrás, mint a ” nagy szürke fal “, nyomtatott könyvek man oldalak (a papír élénkebb volt, mint a tároló). Tehát tudom, hogy ez elegendő ahhoz, hogy valaki új legyen a témában. Az utolsó kérdésed azonban méltányos itt feltenni. Sajnos sem @Kusalananda, sem én magam nem tudok erre válaszolni.
  • @Philippos 🙂 Ja, hogy izgalmas dolog lenne kipróbálni, ” izgalmas “, amely kívül esik az én diagram skáláján.
  • Comeon @Philippos. Tényleg azt mondod Kusalanandának, hogy nem javult a férfi oldalon? 🙂
  • @ZsoltSzilagy Ezt sem nem mondtam, sem nem úgy értettem. Nagyon jól megetetett, csak azt hiszem, elég idős vagy ahhoz, hogy egyedül eszel. (-;

Válasz

Ez a válasz a következő részekben érkezik:

  • A -exec
  • alapértelmezett használata

  • -exec használata a sh -c
  • -exec ... {} +
  • használata -execdir

A -exec

alapértelmezett használata

A -exec opció egy külső segédprogramot igényel, opcionális argumentumokkal, az argumentuma és végrehajtja.

Ha a {} karakterlánc bárhol megtalálható az adott parancsban, akkor annak minden példányát felváltja a jelenleg feldolgozott elérési út ( pl. ./some/path/FILENAME). A legtöbb héjban a két karaktert {} nem kell idézni.

A parancs le kell állítani egy ; felirattal a find számára, hogy megtudja, hol ér véget (mivel később lehetnek további lehetőségek) s). A ; héj elleni védelme érdekében \; vagy ";" , különben a héj a find parancs végének fogja látni.

Példa (a \ a az első két sor vége csak a folytatásra vonatkozik):

find . -type f -name "*.txt" \ -exec grep -q "hello" {} ";" \ -exec cat {} ";" 

Ez megtalálja az összes szokásos fájlt (-type f), amelynek nevei megegyeznek az *.txt mintával az aktuális könyvtárban vagy alatt. Ezután tesztelni fogja, hogy a hello karakterlánc előfordul-e valamelyik megtalált fájlban a grep -q használatával (amely nem hoz létre kimenetet, csak kilépést) állapot). Azon fájlok esetében, amelyek tartalmazzák a karakterláncot, a cat parancs végrehajtásra kerül, hogy a fájl tartalmát a terminálhoz adja ki.

Mindegyik -exec úgy is viselkedik, mint egy “teszt” a find által talált útvonalakon, akárcsak -type és -name igen. Ha a parancs nulla kilépési állapotot ad vissza (ami “sikert” jelent), akkor a find parancs következő részét vesszük figyelembe, különben a find parancs folytatódik a következő útvonalnévvel. Ezt használja a fenti példa a hello karakterláncot tartalmazó fájlok megkeresésére, de az összes többi fájl figyelmen kívül hagyására.

A fenti példa a két leggyakoribb használatot szemlélteti. -exec esetek:

  1. Tesztként a keresés további korlátozására.
  2. Valamilyen művelet végrehajtása a megtaláltakon útvonalnév (általában, de nem feltétlenül a find parancs végén).

a sh -c

kombinációval, amelyet -exec képes végrehajtani, egy külső segédprogramra korlátozódik opcionális argumentumokkal.A shell beépítettek, függvények, feltételek, csővezetékek, átirányítások stb. Közvetlen használata a -exec szolgáltatással csak akkor lehetséges, ha egy sh -c gyermekhéj.

Ha bash funkciókra van szükség, akkor a iv id = helyett használja a bash -c parancsot. “73af3270ae”>

.

sh -c futtatja a /bin/sh parancsfájlot a parancssorban, opcionális parancssori argumentumok követik az adott szkriptet.

Egyszerű példa a sh -c használatára önmagában, find nélkül :

sh -c "echo "You gave me $1, thanks!"" sh "apples" 

Ez két argumentumot ad át a gyermek shell parancsfájlnak. Ezeket a $0 és $1 mappákba helyezzük a szkript használatához.

  1. A string sh. Ez $0 néven lesz elérhető a parancsfájl belsejében, és ha a belső héj hibaüzenetet küld, akkor ezt a karakterláncot fogja előtagolni.

  2. A apples argumentum $1 néven érhető el a szkriptben, és ha több argumentum lett volna, akkor ezek elérhetőek lettek volna $2, $3 stb. Ezek elérhetők lennének a "$@" listában is (kivéve: $0, amely nem lenne a "$@" része).

Ez hasznos -exec -vel kombinálva, mivel ez lehetővé teszi számunkra, hogy önkényesen összetett szkripteket készítsünk, amelyek a find által megtalált útnevekre hatnak.

Példa: Keresse meg az összes szokásos fájlt, amely rendelkezik bizonyos fájlnév utótaggal, és módosítsa ezt a fájlnév utótagot valamilyen más utótagra, ahol az utótagokat változókban tartják:

from=text # Find files that have names like something.text to=txt # Change the .text suffix to .txt find . -type f -name "*.$from" -exec sh -c "mv "$3" "${3%.$1}.$2"" sh "$from" "$to" {} ";" 

Inte belsejében rnal szkript, $1 lenne a karakterlánc text, a $2 karakterlánc a txt és a $3 bármi is lenne, amelyet find megtalált nekünk. A (z) ${3%.$1} kiterjesztés paraméter az útvonalnevet veszi fel, és eltávolítja belőle a .text utótagot.

Vagy a dirname / basename:

find . -type f -name "*.$from" -exec sh -c " mv "$3" "$(dirname "$3")/$(basename "$3" ".$1").$2"" sh "$from" "$to" {} ";" 

vagy hozzáadott változókkal a belső szkript:

find . -type f -name "*.$from" -exec sh -c " from=$1; to=$2; pathname=$3 mv "$pathname" "$(dirname "$pathname")/$(basename "$pathname" ".$from").$to"" sh "$from" "$to" {} ";" 

Vegye figyelembe, hogy ebben az utolsó változatban a from és különbözik az azonos nevű változóktól a külső szkriptben.

A fentiek a helyes módszerek egy tetszőleges komplex szkript meghívására a a következővel: find. A find használata olyan ciklusban, mint a

for pathname in $( find ... ); do 

, hibára hajlamos és inelegáns (személyes vélemény). A fájlnevek felosztása a szóközökön, a fájlnév rángatása, és a héjat arra is kényszeríti, hogy bővítse a find teljes eredményét, mielőtt még a ciklus első iterációját lefuttatná.

Lásd még:


A -exec ... {} +

A végén található ; helyettesíthető a következővel: +. Ez azt eredményezi, hogy find az adott parancsot a lehető legtöbb argumentummal (megtalált elérési utak) hajtja végre, nem pedig minden egyes megtalált útvonalnévnél. A {} karakterláncnak közvetlenül a + előtt kell szerepelnie, hogy működjön .

find . -type f -name "*.txt" \ -exec grep -q "hello" {} ";" \ -exec cat {} + 

Itt a find összegyűjti a kapott útvonalneveket és végrehajtja a cat a lehető legtöbbre egyszerre.

find . -type f -name "*.txt" \ -exec grep -q "hello" {} ";" \ -exec mv -t /tmp/files_with_hello/ {} + 

Hasonlóképpen, itt a mv is végrehajtásra kerül lehetőleg néhányszor. Ez az utolsó példa megköveteli a GNU mv parancsot a coreutils-tól (amely támogatja a -t opciót).

A -exec sh -c ... {} + szintén hatékony módja annak, hogy önkényesen összetett szkript segítségével hurkoljon egy útvonalnévhalmazon.

Az alapok megegyeznek a -exec sh -c ... {} ";", de a szkript most sokkal hosszabb argumentumlistát vesz fel. Ezeket át lehet hurkolni a "$@" átkapcsolásával a szkript belsejében.

Példánk a fájlnév utótagokat megváltoztató utolsó szakaszról:

from=text # Find files that have names like something.text to=txt # Change the .text suffix to .txt find . -type f -name "*.$from" -exec sh -c " from=$1; to=$2 shift 2 # remove the first two arguments from the list # because in this case these are *not* pathnames # given to us by find for pathname do # or: for pathname in "$@"; do mv "$pathname" "${pathname%.$from}.$to" done" sh "$from" "$to" {} + 

A -execdir

használata van még -execdir ( a legtöbb find változat megvalósítja, de nem szabványos opció).

Ez úgy működik, mint a -exec, azzal a különbséggel, hogy az adott shell parancsot a megtalált útvonal könyvtárának aktuális munkakönyvtáraként kell végrehajtani, és hogy A “7b5b2eccc1”> a megtalált elérési út basenime-jét tartalmazza, annak útja nélkül (de a GNU find továbbra is a ./, míg a BSD find nem fogja megtenni).

Példa:

find . -type f -name "*.txt" \ -execdir mv {} done-texts/{}.done \; 

Ez minden megtalált *.txt -fájlt egy már létező done-texts alkönyvtárba helyez át ugyanabban a könyvtárban, mint ahol a fájl volt. talált ra. A fájlt át fogják nevezni úgy is, hogy hozzáadják a .done utótagot.

Ez kicsit bonyolultabb lenne a -exec, mivel a megtalált fájl alapnevét ki kellene szereznünk a {} ből a fájl új nevének kialakításához. Szükségünk van a {} könyvtárnévre is a done-texts könyvtár megfelelő megtalálásához.

-execdir, néhány ilyen dolog könnyebbé válik.

A megfelelő művelet -exec használatával -execdir gyermekhéjat kell alkalmaznia:

find . -type f -name "*.txt" -exec sh -c " for name do mv "$name" "$( dirname "$name" )/done-texts/$( basename "$name" ).done" done" sh {} + 

vagy,

find . -type f -name "*.txt" -exec sh -c " for name do mv "$name" "${name%/*}/done-texts/${name##*/}.done" done" sh {} + 

Megjegyzések

  • -exec vesz egy programot és argumentumokat és futtatja azokat; Néhány shell parancs csak programból és argumentumokból áll, de sokan nem. A shell parancs tartalmazhat átirányítást és csövezést; A -exec nem lehet (bár az egész find átirányítható). A shell parancs használhatja a ; && if stb .; A -exec nem képes, bár a -a -o képes rá. A shell parancs lehet álnév vagy shell függvény, vagy beépített; -exec nem tudja. A shell parancs kibővítheti a varsokat; A -exec nem tud (bár a find futtató külső héj is). A shell parancs minden alkalommal másképp helyettesítheti a $(command) t; -exec nem tudja. …
  • A ‘ sa shell parancs kimondása itt helytelen, find -exec cmd arg \; nem ‘ t héjat hív meg a shell parancssor értelmezéséhez, az közvetlenül a execlp("cmd", "arg") parancsot futtatja, nem pedig execlp("sh", "-c", "cmd arg") (amelyhez a A shell végül a execlp("cmd", "arg") megfelelőjét fogja megtenni, ha a cmd nem épül be).
  • Tisztázhatja, hogy az összes a find argumentumok -exec után és legfeljebb ; vagy töltse ki a végrehajtandó parancsot az argumentumaival együtt, egy {} argumentum minden egyes példányát az aktuális fájlra cserélve (;), és a {}, mint a + előtti utolsó argumentum, amelyet külön argumentumként a fájlok listájával helyettesítenek (a {} + eset). Az IOW -exec több argumentumot vesz fel, amelyeket egy ; vagy {} +.
  • @Kusalananda Nem lenne ‘ t, az utolsó példád is ezzel az egyszerűbb paranccsal működik: find . -type f -name '*.txt' -exec sh -c "mv $1 $(dirname $1)/done-texts/$(basename $1).done" sh {} ';'?
  • @Atralb Igen, ez szintén működött és ugyanolyan hatást váltott ki, mint az utolsó kódrészlet, de a egy ciklusban, megtalált fájlonként egyszer végrehajtja a sh és a mv fájlokat minden megtalált fájlhoz, amelyek észrevehetően lassabb nagy mennyiségű fájl esetén.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük