Narazil jsem na stejný problém na Mac OSX pomocí ZSH shell:v tomto případě neexistuje -t
možnost pro mv
, takže jsem musel najít jiné řešení. Následující příkaz však uspěl:
find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;
Tajemství bylo citovat rovnátka . Není nutné, aby složené závorky byly na konci exec
příkaz.
Testoval jsem pod Ubuntu 14.04 (pomocí BASH a ZSH shelly), funguje to stejně.
Při použití +
znaménko, skutečně se zdá, že musí být na konci exec
příkaz.
Manuálová stránka (nebo online GNU manuál) do značné míry vše vysvětluje.
najít -exec příkaz {} \;
Pro každý výsledek command {}
je proveden. Všechny výskyty {}
jsou nahrazeny názvem souboru. ;
má předponu lomítko, aby jej shell nemohl interpretovat.
najít příkaz -exec {} +
Každý výsledek je připojen k command
a následně proveden. Vezmeme-li v úvahu omezení délky příkazu, domnívám se, že tento příkaz lze provést vícekrát, přičemž mě podporuje manuálová stránka:
celkový počet vyvolání příkazu bude mnohem menší než počet odpovídajících souborů.
Všimněte si tohoto citátu z manuálové stránky:
Příkazový řádek je vytvořen v podstatě stejným způsobem, jakým xargs vytváří své příkazové řádky
Proto nejsou povoleny žádné znaky mezi {}
a +
kromě mezer. +
způsobí, že find zjistí, že argumenty by měly být připojeny k příkazu stejně jako xargs
.
Řešení
Naštěstí GNU implementace mv
může přijmout cílový adresář jako argument buď s -t
nebo delší parametr --target
. Jeho použití bude:
mv -t target file1 file2 ...
Vaše find
příkaz se změní na:
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
Z manuálové stránky:
-exec příkaz;
Vykonat příkaz; true, pokud je vrácen stav 0. Všechny následující argumenty k nalezení jsou považovány za argumenty příkazu až do argumentu sestávajícího z `;' se narazí. Řetězec `{}' je nahrazen aktuálním názvem souboru, který se zpracovává všude, kde se vyskytuje v argumentech příkazu, nejen v argumentech, kde je sám, jako v některých verzích find. Obě tyto konstrukce může být nutné escapovat (s '\') nebo citovat, aby byly chráněny před expanzí pomocí shellu. Příklady použití volby -exec najdete v části PŘÍKLADY. Zadaný příkaz se spustí jednou pro každý odpovídající soubor. Příkaz se provede v počátečním adresáři. Kolem použití akce -exec jsou nevyhnutelné bezpečnostní problémy; místo toho byste měli použít volbu -execdir.
-exec příkaz {} +
Tato varianta akce -exec spustí zadaný příkaz na vybraných souborech, ale příkazový řádek je vytvořen připojením každého vybraného názvu souboru na konec; celkový počet vyvolání příkazu bude mnohem menší než počet odpovídajících souborů. Příkazový řádek je vytvořen v podstatě stejným způsobem, jakým xargs vytváří své příkazové řádky. V rámci příkazu je povolena pouze jedna instance `{}'. Příkaz se provede v počátečním adresáři.
Standardní ekvivalent find -iname ... -exec mv -t dest {} +
pro find
implementace, které nepodporují -iname
nebo mv
implementace, které nepodporují -t
je použít shell ke změně pořadí argumentů:
find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
exec mv "[email protected]" /dest/dir/' sh {} +
Pomocí -name '*.[cC][pP][pP]'
, také se při rozhodování o verzi c
vyvarujeme spoléhání na aktuální národní prostředí nebo p
.
Všimněte si, že +
, na rozdíl od ;
není speciální v žádném shellu, takže nemusí být uvozován (i když citace neuškodí, samozřejmě kromě shellů jako rc
které nepodporují \
jako operátor citace).
Koncové /
v /dest/dir/
je tak, že mv
selže s chybou místo přejmenování foo.cpp
na /dest/dir
v případě, že pouze jeden cpp
soubor byl nalezen a /dest/dir
neexistoval nebo nebyl adresář (nebo symbolický odkaz na adresář).