Skopiuj tylko zwykłe pliki z jednego katalogu do drugiego

12

Chciałbym skopiować zawartość katalogu 1 do katalogu 2. Chciałbym jednak kopiować tylko pliki (a nie katalogi) z mojego katalogu 1. Jak to zrobić?

cp dir1/* dir2/*

nadal mam problem z katalogami.

Ponadto wszystkie moje pliki nie mają żadnego rozszerzenia, więc . nie załatwi sprawy

użytkownik1058398
źródło
1
Nie wiem, co mają z tym wspólnego rozszerzenia.
ctrl-alt-delor
1
cp dir1/* dir2lubcp -t dir2 dir1/*
ctrl-alt-delor
@richard Istnieje dość powszechny zwyczaj wywodzący się ze świata DOS, polegający na nieużywaniu rozszerzeń do katalogów, który nadal do pewnego stopnia przetrwał, co prowadzi do przypuszczenia, że ​​jeśli jest kropka, to nie jest to katalog i odwrotnie.
Gilles „SO- przestań być zły”
ok, ale nadal nie jest to odpowiednie.
ctrl-alt-delor

Odpowiedzi:

18
cp dir1/* dir2

cpnie będzie kopiować katalogów, chyba że zostanie to wyraźnie nakazane ( --recursivena przykład zobacz man cp).

Uwaga 1: cp najprawdopodobniej zakończy działanie ze statusem niezerowym, ale i tak pliki zostaną skopiowane. Może to być problemem, gdy łańcuchowym poleceń na podstawie kodów wyjścia: &&, ||, if cp -r dir1/* dir2; then ..., itd. (Dzięki contrebis na swój komentarz na ten temat )

Uwaga 2 : cpoczekuje, że ostatnim parametrem będzie pojedyncza nazwa pliku lub katalog. Naprawdę nie powinno być znaku wieloznacznego *po nazwie katalogu docelowego. dir2\*zostanie rozszerzony przez powłokę tak jak dir1\*. Niespodziewane rzeczy będzie się zdarzyć:

  • Jeśli dir2jest pusty i zależy od powłoki i ustawień:
    • może pojawić się komunikat o błędzie, który jest najlepszym scenariuszem.
    • dir2/*będą brane dosłownie (szukając nazwanego pliku / katalogu *), co prawdopodobnie doprowadzi również do błędu, chyba że *faktycznie istnieje.
    • dir2/*zostanie po prostu całkowicie usunięty z polecenia, pozostawiając cp dir1/*. Które, w zależności od rozszerzenia dir1/*, mogą nawet zniszczyć dane:
      • Jeśli dir1/*pasuje tylko do jednego pliku lub katalogu, pojawi się błąd z cp.
      • Jeśli dir1/*pasuje dokładnie dwa pliki, jeden zostanie zastąpiony przez drugi ( Zły ).
      • Jeśli dir/*pasuje do wielu plików, a ostatnie dopasowanie to, pojawi się komunikat o błędzie.
      • Jeśli ostatnim dopasowaniem dir/*jest katalog, wszystkie pozostałe dopasowania zostaną do niego przeniesione.
  • Jeśli dir2nie jest pusty, ponownie zależy od:
    • Jeśli ostatnim dopasowaniem dir2/*jest katalog, dir1/*a pozostałe dopasowania dir2/*zostaną przeniesione do.
    • Jeśli ostatnim dopasowaniem dir2/*jest plik, prawdopodobnie pojawi się komunikat o błędzie, chyba że dir1/* pasuje tylko do jednego pliku.
Adaefon
źródło
$ cp dir1/* dir2-> cp: dir1/isadir is a directory (not copied).dla mnie wychodzi ze statusem 1.
contrebis
1
Tak, dla mnie również kończy się ze statusem 1. Ale mimo cpto kopiuje pliki pasujące dir1/*do każdego systemu, który sprawdziłem: Arch Linux, Ubuntu 14.04, OpenBSD 3.9 i 5.5, SuSE Linux 8.1, FreeBSD 6.2, Solaris 8, 9 i 10 (gdzie cpfaktycznie wychodzi z kodem 2). To zachowanie nie jest ani nowe (SuSE 8.1 pochodzi z 2002 r.), Ani nie ogranicza się do Linuksa. cpkończy działanie z niezerowym kodem wyjścia, ponieważ nie mógł zrobić wszystkiego , co mu kazano. To nie znaczy, że nic nie robi .
Adaephon
3
Pewnie, pomyślałem, że warto to zauważyć, ponieważ jeśli łączysz łańcuchy poleceń z &&tym, może to powodować problem. Próbowałem coś takiego, choć nie pamiętam teraz kontekstu.
contrebis,
To nie kopiuje ukrytych plików.
felwithe
@felwithe To, czy *zawiera ukryte pliki, lub jak dołączyć ukryte pliki, zależy od powłoki. Jeśli *nie zawiera ukrytych plików, możesz je dopasować .*. Zauważ, że ten będzie obejmował .i ..na bashi dash, ale nie na zsh. W kontekście tej odpowiedzi możesz uciec, cp dir1/* dir1/.* dir2ponieważ .i ..są katalogami i nie zostaną skopiowane. zshmożna również włączyć do niego ukryte pliki *(D).
Adaephon
7

To powłoka rozwija symbole wieloznaczne, a nie polecenia. Więc cp dir1/* dir2/*najpierw rozwija dwie symbole wieloznaczne, a następnie wywołuje cpwynik. To nie jest to, czego się najwyraźniej spodziewasz: w zależności od liczby plików, które już tam są dir2, dir2/*może rozwinąć się do jednego lub więcej argumentów. Polecenie cpnie wie, które z jego argumentów pochodzą z rozwinięcia pierwszego wzorca, a które z rozwinięcia drugiego wzorca. Oczekuje, że ostatnim argumentem będzie nazwa katalogu docelowego. Zatem, aby skopiować wszystkie pliki z katalogu dir1do katalogu dir2, ostatnim argumentem musi być katalog dir2:

cp dir1/* dir2

Ponieważ *pasuje do wszystkich plików, cppróbuje skopiować wszystkie pliki. Obejmuje to katalogi: katalogi też są plikami. Pomija katalogi, ale zgłasza błąd. Kopiuje zawartość specjalnych plików, takich jak nazwane potoki (coś lepiej do nich pisać, lub cpbędzie blokować) itp.

Aby skopiować tylko zwykłe pliki, musisz ograniczyć dopasowanie. W zsh możesz użyć do tego kwalifikatora glob . :

cp dir1/*(.) dir2

Inne muszle tego nie mają. Możesz użyć findpolecenia do filtrowania według typów plików. Zakładając, że korzystasz z niewbudowanego systemu Linux lub Cygwin:

find dir1 -maxdepth 1 -type f -exec cp -t dir2 {} +

W systemach Linux, FreeBSD i OSX:

find dir1 -maxdepth 1 -type f | xargs -I {} cp {} dir2
Gilles „SO- przestań być zły”
źródło
Czy istnieje powód, aby to określić -maxdepth 1. Czy istnieje sposób rekurencyjnego kopiowania i zachowania oryginalnej hierarchii katalogów w katalogu docelowym?
Abdull,
@Abdull Bez -maxdepth 1The findkomenda będzie rekursja do podkatalogów, których nie chciano tu. Jeśli chcesz skopiować całe drzewo katalogów, w tym podkatalogów, to zupełnie inna kwestia, a odpowiedź jest dużo prostsza: cp -a dir1 dir2.
Gilles 'SO - przestań być zły'
0

Poniżej znajduje się polecenie skopiowania pliku ze źródła do katalogu docelowego.

  1. Przejdź do folderu źródłowego, a następnie napisz poniżej polecenie:

    $ cp fileName destination directory path

Przykład:

cp publichOT.sh  /data/home/useradmin
Tapan Dubey
źródło