Zkopírujte konkrétní typ souboru a zachovejte strukturu složek
On 10 února, 2021 by adminMám strukturu složek s hromadou souborů * .csv roztroušených po složkách. Nyní chci zkopírovat všechny soubory * .csv do jiného cíle při zachování struktury složek.
Funguje to tak, že:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target ...
a atd., ale chtěl bych to udělat pomocí jednoho příkazu.
Odpověď
find
má velmi praktickou -exec
možnost:
find . -name "*.csv" -exec cp --parents \{\} /target \;
Komentáře
- pravděpodobně kvůli tomu \ {\} \;
-
'{}'
funguje stejně dobře - i když
-execdir
je bezpečnější než-exec
, jednoduše nahrazení jedné za druhou nezachová strukturu složek, jak bylo zamýšleno. - Proč dostat zprávu ' Vynechání adresáře ', když se je pokusím zkopírovat pomocí vašeho příkazu?
- Můžete vysvětlit, proč zde musíte uniknout složené závorky?
Odpovědět
Můžete také použít rsync
pro toto.
$ rsync -a --prune-empty-dirs --include "*/" --include "*.csv" --exclude "*" source/ target/
Pokud si chcete ponechat prázdné adresáře ze zdrojového stromu, přeskočte možnost --prune-empty-dirs
:
$ rsync -a --include "*/" --include "*.csv" --exclude "*" source/ target/
Pokud nechcete zachovat symbolické odkazy, data úprav, oprávnění k souborům, vlastníky atd., nahraďte -a
s jinou kombinací -rlptgoD
. 😉
Komentáře
Odpověď
Můžete použít najít a cpio v režimu průchodu
find . -name "*.csv" | cpio -pdm /target
Najdete zde všechny soubory .csv v aktuálním adresáři a níže a zkopírujte je do / target zachováním adresářové struktury zakořeněné v .
.
Pokud používáte
find /path/to/files -name "*.csv" | cpio -pdm /target
vyhledá celý soubor v /path/to/files
a níže a zkopíruje je do /target/path/to/files
a níže .
Komentáře
- Zkoušel jsem všechny odpovědi shora dolů až na tuto a byla to jediná, která fungovala na první pokus
- Toto by měla být přijatá odpověď.
- Dokumenty GNU mi byly užitečné: " V režimu kopírování předá [požadavek
-p
, cpio] čte seznam souborů ke kopírování ze standardního vstupu; adresář, do kterého je zkopíruje, je uveden jako nepovinný argument. " … " -d V případě potřeby vytvořte přední adresáře. " … " -m Zachovat předchozí časy úprav souborů při vytváření souborů. "
Odpověď
Příkaz cp
umožňuje více zdrojových argumentů:
cp **/*.csv --parents ../target
CAVEAT: používám zde rekurzivní glob; toto je možnost globstar
v Bash 4+ a ksh
a je ve výchozím nastavení podporováno v zsh
. Rekurzivní globusy ne odpovídají skrytým souborům a složkám a některé implementace sledují symbolické odkazy, zatímco jiné nikoli .
Pokud váš shell nefunguje “ t supp ort rekurzivní globusy, nebo pokud je nechcete používat, můžete provést následující:
-
*.csv */*.csv */*/*.csv */*/*/*.csv
– to je samozřejmě velmi nadbytečné a vyžaduje vědět, jak hluboká je vaše adresářová struktura. -
$(find . -name "*.csv")
– Toto bude odpovídá skrytým souborům a složkám.find
podporuje také specifikaci, zda mají být použity symbolické odkazy, což může být užitečné.
Komentáře
- to je přesně to, co jsem zkoušel (rekurzivní glob) a našel jsem nějaké, ale ne všechny? docela divný. Při použití skriptu npm copyfiles mám stejný přesný výsledek, ale pokud použiji příkaz find, najde vše …
- @Randyaa ' budu nějaké potřebovat více podrobností o tom, které soubory přesně nebyly ' nalezeny, aby vám pomohly. Diskuse zde a pokračování zde o přesném chování rekurzivního globálu vám může být užitečná .
- Ukázalo se, že rekurzivní glob nebyl ' z nějakého důvodu povolen …Nikdy předtím jsem na to ' nenarazil, ale opravil jsem to pouhým provedením
shopt -s globstar
bezprostředně před mým příkazem a vše je v pořádku. Děkuji za následnou kontrolu! -
--parents
bylo to, co jsem hledal. děkuji
odpověď
Tenhle pracoval pro mě:
find -name "*.csv" | xargs cp --parents -t /target
Komentáře
- Nejlepší odpověď s nejjednodušší syntaxí. Funguje dobře a je snadno zapamatovatelný. V mnoha případech je
find [things] | xargs [do stuff]
velmi silný. - Souhlasím. Ve srovnání s některými dalšími odpověďmi velmi přímočaré.
- Přestávky, pokud máte v názvech souborů mezery
- @MichelePiccolini Mezery v názvech souborů lze zpracovat pomocí
find -print0
axargs -0
.
Odpověď
Od rsync
„s stránka:
-R, –relative
Použijte relativní cesty. To znamená, že se na server odešlou úplné názvy cest zadané v příkazovém řádku, nikoli pouze poslední části názvů souborů. To je užitečné zejména v případě, že chcete odeslat několik různých adresářů současně. Například pokud jste použili tento příkaz:
rsync -av /foo/bar/baz.c remote:/tmp/
… vytvoří se soubor s názvem baz.c v / tmp / na vzdáleném počítači. Pokud jste místo toho použili
rsync -avR /foo/bar/baz.c remote:/tmp/
poté by se na vzdáleném počítači vytvořil soubor s názvem /tmp/foo/bar/baz.c, který by zachoval jeho úplnou cestu. Tyto další prvky cesty se nazývají “ impli ed adresáře “(tj. adresáře „foo“ a „foo / bar“ ve výše uvedeném příkladu).
Takže by to fungovalo také:
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Komentáře
- Děkujeme za poskytnutí této odpovědi. Kompatibilní s BSD userland (macOS), a cestami s mezerami.
Odpověď
Za předpokladu, že chcete tuto strukturu replikovat z ./source
na ./destination
:
cd source find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)
Jsem připraven počítat to jako jeden řádek, přičemž cd source
je integrovaný shell.
Komentáře
-
tar
má možnost-C
, aby nemusel nejprve měnit adresář.
-m
je zkratka pro--prune-emty-dirs
.-R
, která zkopíruje nadřazenou adresářovou strukturu zdroje. (viz moje odpověď zde.)