Kopiera specifik filtyp och behåll mappstrukturen
On februari 10, 2021 by adminJag har en mappstruktur med en massa * .csv-filer spridda över mapparna. Nu vill jag kopiera alla * .csv-filer till en annan destination och hålla mappstrukturen.
Det fungerar genom att göra:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target ...
och så vidare, men jag skulle vilja göra det med ett kommando.
Svar
find
har ett mycket praktiskt -exec
-alternativ:
find . -name "*.csv" -exec cp --parents \{\} /target \;
Kommentarer
- Förmodligen på grund av detta \ {\} \;
-
'{}'
fungerar lika bra - Även om
-execdir
är säkrare än-exec
, att helt enkelt ersätta den ena med den andra behåller inte mappstrukturen som avsett. - Varför jag få meddelande ' Utelämna katalog ' när jag försöker kopiera dem med ditt kommando?
- Kan du förklara varför hängslen måste undkommas här?
Svar
Du kan också använda rsync
för detta.
$ rsync -a --prune-empty-dirs --include "*/" --include "*.csv" --exclude "*" source/ target/
Om du vill behålla tomma kataloger från källträdet, hoppa över --prune-empty-dirs
-alternativet:
$ rsync -a --include "*/" --include "*.csv" --exclude "*" source/ target/
Om du inte vill att symlänkar, ändringsdatum, filbehörigheter, ägare etc. ska bevaras, ersätt -a
med en annan kombination av -rlptgoD
. 😉
Kommentarer
Svar
Du kan använda hitta och cpio i passeringsläge
find . -name "*.csv" | cpio -pdm /target
Här hittar du alla .csv-filer i den aktuella katalogen och nedan och kopiera dem till / target underhålla katalogstrukturen rotad i .
.
Om du använder
find /path/to/files -name "*.csv" | cpio -pdm /target
den hittar hela filen i /path/to/files
och nedan och kopierar dem till /target/path/to/files
och nedan .
Kommentarer
- Jag försökte alla svaren uppifrån och upp till den här, och det här var det enda som fungerade vid första försöket
- Detta borde vara det accepterade svaret.
- Jag tyckte att GNU docs var till hjälp: " I kopieringspassläge läser [begärs av
-p
, cpio] listan över filer som ska kopieras från standardingången; katalogen till vilken den ska kopieras ges som ett icke-alternativargument. " … " -d Skapa ledande kataloger där det behövs. " … " -m Behåll tidigare filändringstider när du skapar filer. "
Svar
cp
-kommandot tillåter flera källargument:
cp **/*.csv --parents ../target
CAVEAT: Jag använder en rekursiv glob här; detta är globstar
i Bash 4+ och ksh
och stöds som standard i zsh
. Rekursiva globar gör inte matchar dolda filer och mappar, och vissa implementeringar följer symlänkar medan andra inte .
Om ditt skal inte fungerar t supp eller rekursiva globs, eller om du föredrar att inte använda dem kan du göra följande:
-
*.csv */*.csv */*/*.csv */*/*/*.csv
– det här är naturligtvis mycket överflödig och kräver att du vet hur djup din katalogstruktur är. -
$(find . -name "*.csv")
– Denna kommer matchar dolda filer och mappar.find
stöder också att ange om symlänkar följs eller inte, vilket kan vara användbart.
Kommentarer
- det här är precis vad jag försökte (den rekursiva globen) och det hittade några men inte alla? ganska konstigt. Jag fick samma exakta resultat när jag använde npm copyfiles-skriptet, men om jag använder kommandot find hittar det allt …
- @Randyaa I ' Jag behöver lite mer information om vilka filer exakt ' inte hittades för att hjälpa dig. Du kan hitta diskussionen här och fortsatte här om det exakta beteendet hos den rekursiva globen som användbar .
- visar sig att rekursiv glob inte var ' t aktiverad av någon anledning …Jag ' har aldrig stött på detta förut men jag korrigerade det med bara en exekvering av
shopt -s globstar
omedelbart före mitt kommando och allt går bra. Tack för uppföljningen! -
--parents
var det jag letade efter. tack
Svar
Den här fungerade för mig:
find -name "*.csv" | xargs cp --parents -t /target
Kommentarer
- Bästa svaret med mest enkla syntax. Fungerar bra och är lätt att komma ihåg. I många fall är
find [things] | xargs [do stuff]
väldigt kraftfull. - Överens. Mycket enkelt jämfört med några av de andra svaren.
- Avbrott om du har mellanslag i filnamn
- @MichelePiccolini Utrymmen i filnamn kan hanteras med
find -print0
ochxargs -0
.
Svar
Från rsync
”s manpage:
-R, –relative
Använd relativa sökvägar. Detta innebär att de fullständiga sökvägsnamnen som anges på kommandoraden skickas till servern snarare än bara de sista delarna av filnamnen. Detta är särskilt användbart när du vill skicka flera olika kataloger samtidigt, till exempel om du använde det här kommandot:
rsync -av /foo/bar/baz.c remote:/tmp/
… detta skulle skapa en fil med namnet baz.c i / tmp / på fjärrmaskinen. Om du istället använde
rsync -avR /foo/bar/baz.c remote:/tmp/
då skulle en fil med namnet /tmp/foo/bar/baz.c skapas på fjärrmaskinen, vilket bibehåller hela sökvägen. Dessa extra banelement kallas ” impli ed kataloger ”(dvs. katalogerna ”foo” och ”foo / bar” i exemplet ovan).
Så det skulle också fungera:
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Kommentarer
- Tack för att du har svarat. Kompatibel med BSD userland (macOS), och banor med mellanslag i dem.
Svar
Förutsatt att du vill replikera denna struktur från ./source
till ./destination
:
cd source find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)
Jag är beredd att räkna det som en rad, varvid cd source
är ett inbyggt skal.
Kommentarer
-
tar
har-C
för att undvika att behöva ändra katalogen först.
-m
är en genväg för--prune-emty-dirs
.-R
kan också läggas till för att kopiera källans överordnade katalogstruktur. (jfr mitt svar här.)