Kopier spesifikk filtype og hold mappestrukturen
On februar 10, 2021 by adminJeg har en mappestruktur med en haug med * .csv-filer spredt over mappene. Nå vil jeg kopiere alle * .csv-filer til en annen destinasjon og holde mappestrukturen.
Det fungerer ved å gjøre:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target ...
og så videre, men jeg vil gjøre det ved å bruke en kommando.
Svar
find
har et veldig praktisk -exec
alternativ:
find . -name "*.csv" -exec cp --parents \{\} /target \;
Kommentarer
- Sannsynligvis på grunn av dette \ {\} \;
-
'{}'
fungerer like bra - Selv om
-execdir
er tryggere enn-exec
, bare å erstatte den ene med den andre bevarer ikke mappestrukturen slik den var ment. - Hvorfor jeg få melding ' Utelater katalog ' når jeg prøver å kopiere dem med kommandoen din?
- Kan du forklare hvorfor bukseseler må rømmes her?
Svar
Du kan også bruke rsync
for dette.
$ rsync -a --prune-empty-dirs --include "*/" --include "*.csv" --exclude "*" source/ target/
Hvis du vil beholde tomme kataloger fra kildetreet, hopper du over --prune-empty-dirs
-alternativet:
$ rsync -a --include "*/" --include "*.csv" --exclude "*" source/ target/
Hvis du ikke vil ha symlinker, modifikasjonsdatoer, filtillatelser, eiere osv. bevart, må du erstatte -a
med en annen kombinasjon av -rlptgoD
. 😉
Kommentarer
Svar
Du kan bruke finn og cpio i pass-modus
find . -name "*.csv" | cpio -pdm /target
Dette finner alle .csv-filer i den nåværende katalogen og under, og kopier dem til / mål ved å opprettholde katalogstrukturen forankret i .
.
Hvis du bruker
find /path/to/files -name "*.csv" | cpio -pdm /target
den finner hele filen i /path/to/files
og under og kopierer dem til /target/path/to/files
og under .
Kommentarer
- Jeg prøvde alle svarene ovenfra og ned til denne, og dette var den eneste som fungerte i første forsøk
- Dette skal være det aksepterte svaret.
- Jeg fant GNU docs nyttig: " I kopi-pass-modus leser [forespurt av
-p
alternativet, cpio] listen over filer som skal kopieres fra standardinngangen; katalogen som den vil kopiere dem til er gitt som et ikke-alternativt argument. " … " -d Lag ledende kataloger der det trengs. " … " -m Behold tidligere filendringstider når du oppretter filer. "
Svar
cp
-kommandoen tillater flere kildeargumenter:
cp **/*.csv --parents ../target
CAVEAT: Jeg bruker en rekursiv glob her; dette er globstar
-alternativet i Bash 4+ og ksh
, og støttes som standard i zsh
. Rekursive globs ikke samsvarer med skjulte filer og mapper, og noen implementeringer følger symlenker mens andre ikke .
Hvis skallet ditt ikke gjør det » t supp eller rekursive globs, eller hvis du foretrekker å ikke bruke dem, kan du gjøre følgende:
-
*.csv */*.csv */*/*.csv */*/*/*.csv
– dette er selvfølgelig veldig overflødig og krever å vite hvor dyp katalogstrukturen din er. -
$(find . -name "*.csv")
– Denne vil samsvarer med skjulte filer og mapper.find
støtter også å spesifisere om symlinker følges eller ikke, noe som kan være nyttig.
Kommentarer
- dette er akkurat det jeg prøvde (den rekursive globen) og den fant noen, men ikke alle? ganske rart. Jeg fikk det samme eksakte resultatet når jeg bruker npm copyfiles-skriptet, men hvis jeg bruker finn-kommandoen, finner den alt …
- @Randyaa Jeg ' Jeg trenger litt flere detaljer om hvilke filer, nøyaktig, som ikke ' ble funnet for å hjelpe deg. Du kan finne diskusjonen her og fortsatte her om den presise oppførselen til den rekursive globen som nyttig .
- viser seg at rekursiv glob ikke var ' t aktivert av en eller annen grunn …Jeg ' har aldri kjørt på dette før, men jeg korrigerte det med bare en utførelse av
shopt -s globstar
rett før kommandoen min og alt er bra. Takk for oppfølgingen! -
--parents
var det jeg lette etter. takk
Svar
Denne fungerte for meg:
find -name "*.csv" | xargs cp --parents -t /target
Kommentarer
- Beste svaret med mest enkel syntaks. Fungerer helt fint og er lett å huske. I mange tilfeller er
find [things] | xargs [do stuff]
veldig kraftig. - Avtalt. Veldig grei sammenlignet med noen av de andre svarene.
- Pauser hvis du har mellomrom i filnavn
- @MichelePiccolini Rom i filnavn kan håndteres med
find -print0
ogxargs -0
.
Svar
Fra rsync
«s manpage:
-R, –relative
Bruk relative stier. Dette betyr at de fullstendige banenavnene som er spesifisert på kommandolinjen blir sendt til serveren i stedet for bare de siste delene av filnavnene. Dette er spesielt nyttig når du vil sende flere forskjellige kataloger samtidig. For eksempel hvis du brukte denne kommandoen:
rsync -av /foo/bar/baz.c remote:/tmp/
… dette vil opprette en fil som heter baz.c i / tmp / på den eksterne maskinen. Hvis du i stedet brukte
rsync -avR /foo/bar/baz.c remote:/tmp/
så opprettes en fil med navnet /tmp/foo/bar/baz.c på den eksterne maskinen, og den bevarer hele banen. Disse ekstra baneelementene kalles impli ed kataloger «(dvs. katalogene «foo» og «foo / bar» i eksemplet ovenfor).
Så dette vil også fungere:
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Kommentarer
- Takk for at du ga dette svaret. Kompatibel med BSD brukerland (macOS), og stier med mellomrom i.
Svar
Forutsatt at du vil replikere denne strukturen fra ./source
til ./destination
:
cd source find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)
Jeg er forberedt på å telle det som en linje, og cd source
er et innebygd skall.
Kommentarer
-
tar
har-C
alternativet for å unngå å måtte endre katalogen først.
-m
er en snarvei for--prune-emty-dirs
.-R
kan også legges til for å kopiere kildens overordnede katalogstruktur. (jfr. svaret mitt her.)