Skopiuj określony typ pliku zachowując strukturę folderów


108

Mam strukturę folderów z wieloma plikami * .csv rozrzuconymi po folderach. Teraz chcę skopiować wszystkie pliki * .csv do innego miejsca docelowego, zachowując strukturę folderów.

Działa poprzez:

cp --parents *.csv /target
cp --parents */*.csv" /target
cp --parents */*/*.csv /target
cp --parents */*/*/*.csv /target
...

i tak dalej, ale chciałbym to zrobić za pomocą jednego polecenia.

Odpowiedzi:


126

Czy jest jakiś powód, dla którego ludzie nie chcą używać find's -exec? To bardzo przydatne.

find . -name '*.csv' -exec cp --parents \{\} /target \;

Poznaj swoje narzędzia. ;-)


62
Prawdopodobnie z tego powodu \ {\} \;
igo

12
'{}'działa równie dobrze
OrangeDog

3
Chociaż -execdirjest to bezpieczniejsze niż -execzwykłe zastąpienie jednego z drugim nie zachowuje struktury folderów zgodnie z przeznaczeniem.
Simon Shine

2
Dlaczego pojawia się komunikat „Pominięcie katalogu”, gdy próbuję skopiować je za pomocą polecenia?
Vicky Dev,

4
Czy potrafisz wytłumaczyć, dlaczego trzeba tutaj uciec?
Noumenon

46

Możesz również użyć rsyncdo tego.

$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/

Jeśli chcesz zachować puste katalogi z drzewa źródłowego, pomiń --prune-empty-dirsopcję:

$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/

Jeśli nie chcesz zachować dowiązań symbolicznych, dat modyfikacji, uprawnień do plików, właścicieli itp., Zamień na -ainną kombinację -rlptgoD. ;-)


1
-mjest skrótem do --prune-emty-dirs.
Geremia

Można także -Rdodać opcję kopiowania struktury katalogu nadrzędnego źródła. (por. moja odpowiedź tutaj.)
Geremia,

-R działa dla mnie! Dzięki
gigi2

32

Możesz użyć funkcji Znajdź i CPIO w trybie przejścia

find . -name '*.csv' | cpio -pdm  /target

To znajdzie wszystkie pliki .csv w bieżącym katalogu i poniżej i skopiuje je do / target, utrzymując strukturę katalogu zakorzenioną ..

Jeśli użyjesz

find /path/to/files -name '*.csv' | cpio -pdm /target

znajdzie wszystkie pliki w /path/to/filesi poniżej oraz skopiuje je do /target/path/to/filesi poniżej.


3
Próbowałem wszystkich odpowiedzi od góry do góry, i to była jedyna, która zadziałała przy pierwszej próbie
OscarRyz

21

cpPolecenie zezwala wiele argumentów źródłowych:

cp **/*.csv --parents ../target

CAVEAT: Używam tutaj globu rekurencyjnego; jest to globstaropcja w Bash 4+ kshi jest domyślnie obsługiwana w zsh. Globy rekurencyjne nie pasują do ukrytych plików i folderów, a niektóre implementacje podążają za dowiązaniami symbolicznymi, a inne nie .

Jeśli twoja powłoka nie obsługuje rekurencyjnych globów lub wolisz ich nie używać, możesz wykonać następujące czynności:

  • *.csv */*.csv */*/*.csv */*/*/*.csv - jest to oczywiście bardzo zbędne i wymaga znajomości głębokości struktury katalogów.
  • $(find . -name '*.csv')- To będzie dopasować ukryte pliki i foldery. findobsługuje także określanie, czy mają być stosowane dowiązania symboliczne, co może być przydatne.

właśnie tego próbowałem (glob rekurencyjny) i znalazłem niektóre, ale nie wszystkie? dość dziwne. Ten sam dokładny wynik uzyskałem przy użyciu skryptu npm copyfiles, ale jeśli użyję polecenia find, to wszystko znajdzie ...
Randyaa,

@ Randyaa Potrzebuję więcej szczegółów na temat tego, które pliki nie zostały znalezione, aby ci pomóc. Można znaleźć dyskusję tutaj i nadal tu o precyzyjne zachowanie rekurencyjnego glob użytecznego.
Kyle Strand,

1
okazuje się, że glob globalny rekurencyjny nie został włączony z jakiegoś powodu ... Nigdy wcześniej na to nie wpadłem, ale poprawiłem go wykonując shopt -s globstarpolecenie tuż przed moim poleceniem i wszystko jest w porządku. Dzięki za kontynuację!
Randyaa,

--parentstego szukałem. dzięki
Josh

17

Ten działał dla mnie:

find -name "*.csv" | xargs cp --parents -t /target


Najlepsza odpowiedź z najprostszą składnią. Działa dobrze i jest łatwy do zapamiętania. W wielu przypadkach find [things] | xargs [do stuff]jest bardzo potężny.
Codziennie astronauta

Zgoda. Bardzo proste w porównaniu do niektórych innych odpowiedzi.
Tim B

1
Łamie się, jeśli masz spacje w nazwach plików
Michele Piccolini

@MichelePiccolini Spacje w nazwach plików mogą być obsługiwane za pomocą find -print0i xargs -0.
pasztorpisti

8

Zakładając, że chcesz powtórzyć tę strukturę od ./sourcedo ./destination:

cd source
find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)

Jestem gotów policzyć to jako jedną linię, ponieważ cd sourcejest to wbudowana powłoka.


2
Nie sądzę, żeby naprawdę miał na myśli jedno polecenie - po prostu nie trzeba się pieprzyć jak jego przykład;)

tarma -Copcję uniknięcia pierwszej zmiany katalogu.
Bart

8

Z rsyncstrony podręcznika:

-R, - względne

Użyj ścieżek względnych. Oznacza to, że pełne nazwy ścieżek określone w wierszu poleceń są wysyłane na serwer, a nie tylko ostatnie części nazw plików. Jest to szczególnie przydatne, gdy chcesz wysłać kilka różnych katalogów jednocześnie. Na przykład, jeśli użyłeś tego polecenia:

rsync -av /foo/bar/baz.c remote:/tmp/

... utworzy to plik o nazwie baz.c w / tmp / na zdalnym komputerze. Jeśli zamiast tego użyłeś

rsync -avR /foo/bar/baz.c remote:/tmp/

następnie plik o nazwie /tmp/foo/bar/baz.c zostanie utworzony na komputerze zdalnym, zachowując pełną ścieżkę. Te dodatkowe elementy ścieżki są nazywane „katalogami domyślnymi” (tj. Katalogami „foo” i „foo / bar” w powyższym przykładzie).

To też by działało:

rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.