Kopier specifik filtype, og hold mappestrukturen
On februar 10, 2021 by adminJeg har en mappestruktur med en masse * .csv-filer spredt over mapperne. Nu vil jeg kopiere alle * .csv-filer til en anden destination og holde mappestrukturen.
Det fungerer ved at gøre:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target ...
og så videre, men jeg vil gerne gøre det ved hjælp af en kommando.
Svar
find
har en meget praktisk -exec
mulighed:
find . -name "*.csv" -exec cp --parents \{\} /target \;
Kommentarer
- Sandsynligvis på grund af dette \ {\} \;
-
'{}'
fungerer lige så godt - Selvom
-execdir
er sikrere end-exec
, simpelthen at erstatte den ene med den anden bevarer ikke mappestrukturen som beregnet. - Hvorfor jeg få besked ‘ Udeladelse af bibliotek ‘ når jeg prøver at kopiere dem med din kommando?
- Kan du forklare, hvorfor her skal seler være undsluppet?
Svar
Du kan også bruge rsync
til dette.
$ rsync -a --prune-empty-dirs --include "*/" --include "*.csv" --exclude "*" source/ target/
Hvis du vil beholde tomme mapper fra kildetræet, skal du springe indstillingen --prune-empty-dirs
over:
$ rsync -a --include "*/" --include "*.csv" --exclude "*" source/ target/
Hvis du ikke vil have symlinks, ændringsdatoer, filtilladelser, ejere osv. bevaret, skal du udskifte -a
med en anden kombination af -rlptgoD
. 😉
Kommentarer
Svar
Du kan bruge find og cpio i gennemløbstilstand
find . -name "*.csv" | cpio -pdm /target
Dette finder alle .csv-filer i den aktuelle mappe og derunder, og kopier dem til / target vedligeholdelse af mappestrukturen rodfæstet i .
.
Hvis du bruger
find /path/to/files -name "*.csv" | cpio -pdm /target
den finder hele filen i /path/to/files
og derunder og kopierer dem til /target/path/to/files
og derunder .
Kommentarer
- Jeg prøvede alle svarene ovenfra og ned til denne ene, og dette var den eneste, der fungerede ved første forsøg
- Dette skal være det accepterede svar.
- Jeg fandt, at GNU docs var nyttig: ” I kopipassetilstand [anmodet af
-p
, cpio] læser listen over filer, der skal kopieres fra standardindgangen; den mappe, som den vil kopiere dem til, gives som et argument uden valgmulighed. ” … ” -d Opret førende mapper, hvor det er nødvendigt. ” … ” -m Behold tidligere tidspunkter for filændring når du opretter filer. ”
Svar
cp
kommandoen tillader flere kildeargumenter:
cp **/*.csv --parents ../target
CAVEAT: Jeg bruger her en rekursiv glob; dette er globstar
i Bash 4+ og ksh
, og understøttes som standard i zsh
. Rekursive globs skal ikke matcher skjulte filer og mapper, og nogle implementeringer følger symlinks, mens andre ikke .
Hvis din shell ikke gør ” t supp eller rekursive globs, eller hvis du foretrækker ikke at bruge dem, kan du gøre følgende:
-
*.csv */*.csv */*/*.csv */*/*/*.csv
– dette er selvfølgelig meget overflødig og kræver at vide, hvor dyb din bibliotekstruktur er. -
$(find . -name "*.csv")
– Denne vil matcher skjulte filer og mapper.find
understøtter også angivelse af, om symlinks er fulgt eller ej, hvilket kan være nyttigt.
Kommentarer
- dette er præcis det, jeg prøvede (den rekursive glob), og den fandt nogle, men ikke alle? ret underligt. Jeg fik det samme nøjagtige resultat, når jeg bruger npm copyfiles-scriptet, men hvis jeg bruger find-kommandoen, finder den alt …
- @Randyaa I ‘ Jeg har brug for noget flere detaljer om, hvilke filer der præcist blev fundet ‘ for at hjælpe dig. Du finder muligvis diskussionen her og fortsatte her om den nøjagtige opførsel af den rekursive glob nyttig .
- viser sig, at rekursiv glob ikke var ‘ t aktiveret af en eller anden grund …Jeg ‘ har aldrig stødt på dette før, men jeg rettede det med bare en udførelse af
shopt -s globstar
umiddelbart før min kommando, og alt er i orden. Tak for opfølgningen! -
--parents
var det, jeg ledte efter. tak
Svar
Denne fungerede for mig:
find -name "*.csv" | xargs cp --parents -t /target
Kommentarer
- Bedste svar med den mest enkle syntaks. Fungerer fint og er let at huske. I mange tilfælde er
find [things] | xargs [do stuff]
meget stærk. - Aftalt. Meget ligetil i forhold til nogle af de andre svar.
- Brud, hvis du har mellemrum i filnavne
- @MichelePiccolini Rum i filnavne kan håndteres med
find -print0
ogxargs -0
.
Svar
Fra rsync
“s manpage:
-R, –relativ
Brug relative stier. Dette betyder, at de fulde stienavne, der er angivet på kommandolinjen, sendes til serveren i stedet for kun de sidste dele af filnavnene. Dette er især nyttigt, når du vil sende flere forskellige kataloger på samme tid. denne kommando:
rsync -av /foo/bar/baz.c remote:/tmp/
… dette ville skabe en fil med navnet baz.c i / tmp / på den eksterne maskine. Hvis du i stedet brugte
rsync -avR /foo/bar/baz.c remote:/tmp/
så oprettes en fil med navnet /tmp/foo/bar/baz.c på den eksterne maskine, idet den bevarer sin fulde sti. Disse ekstra stielementer kaldes ” impli ed mapper “(dvs. katalogerne “foo” og “foo / bar” i ovenstående eksempel).
Så dette ville også fungere:
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Kommentarer
- Tak for dit svar. Kompatibel med BSD-brugerland (macOS), og stier med mellemrum i dem.
Svar
Forudsat at du vil replikere denne struktur fra ./source
til ./destination
:
cd source find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)
Jeg er parat til at tælle det som en linje, idet cd source
er en shell-indbygget.
Kommentarer
-
tar
har indstillingen-C
for at undgå at skulle ændre kataloget først.
-m
er en genvej til--prune-emty-dirs
.-R
tilføjes for at kopiere kildens overordnede biblioteksstruktur. (jf. mit svar her.)