Jak mogę rekursywnie przenieść wszystkie pliki z podkatalogów do jednego katalogu?

10

Próbuję zebrać wszystkie pliki w bieżącym katalogu i wszystkie podkatalogi w jednym katalogu. Próbuję czegoś takiego

find -type f -exec mv {} collection/{} \; 

powyższe polecenie nie zadziała, ponieważ drugie {}daje pełną ścieżkę, jak mogę zebrać wszystkie pliki?

Królik
źródło

Odpowiedzi:

14

Usuń {}z mv, mvweźmie to jako katalog docelowy, ignorując katalogi nadrzędne:

find -type f -exec mv {} collection/ \;
Lekensteyn
źródło
och, to nie przyszło mi do głowy. dzięki :)
Bunny Rabbit
Jak mówię w odpowiedzi na pytanie, jest to potencjalnie zły pomysł. Może użycie argumentu -maxdepth 1pomogłoby.
loevborg
Pomyśl o tym, wygląda na to, że źle odczytałem twoje pytanie :) Przepraszam.
loevborg
@loevborg: Dodałem „rekurencyjnie” do tytułu. Jeśli nadal występują pomyłki, edytuj i
popraw
1
szybszą odmianą tej odpowiedzi jestfind -type f -print0|xargs -0r mv -it colection/
hildred
5

Zamiast używać find(co dobrze wykonuje zadanie), możesz również użyć powłoki w tym celu.

Powiedz, że chcesz mieć wszystkie pliki od $ PWD do $ DEST. Naturalną próbą byłoby:

mv $PWD/* $DEST

Jak to działa? Wyrażenie „$ PWD / *” rozwija się do nazw wszystkich plików w tym katalogu. Ta funkcja powłoki nazywa się „globowaniem”. Ostatnim argumentem mvjest katalog docelowy. Jeśli masz bardzo wiele plików, to nie zadziała, ponieważ długość wiersza polecenia jest ograniczona.

Ale rozwiązanie ma problem polegający na tym, że pomija pliki kropkowe - lub „ukryte” pliki, pliki i katalogi, których nazwa zaczyna się od „.”. Aby rozwiązać ten problem, musisz powiedzieć swojej powłoce, aby dołączała pliki kropkowe podczas globowania. Aby to zrobić, użyj

shopt -s dotglob

podczas korzystania bash(i prawdopodobnie używasz, bashchyba że zmieniłeś ustawienie domyślne). W tej powłoce powyższe polecenie będzie również działać dla plików dot.

Nawiasem mówiąc, w zsh, masz możliwość wyboru tego na podstawie indywidualnych przypadków. Aby to zrobić, włóż

setopt extendedglob

w twoim .zshrc. Następnie możesz użyć

mv $PWD/*(D) $DEST

aby przenieść wszystkie pliki, w tym pliki kropkowe. („D” powoduje tymczasowe włączenie opcji „GLOB_DOTS”).

Pierwotnym pytaniem było przeniesienie wszystkich zwykłych plików (nie katalogów) ze wszystkich podkatalogów i ich podkatalogów do jednego katalogu. Można to osiągnąć za pomocą zsh:

mv $PWD/**/*(D.)

Wyrażenie to **/*powoduje, że globber schodzi rekurencyjnie do podkatalogów. Te Dśrodki „również wybrać dotfiles; to .znaczy«wybrać tylko zwykłe pliki, nie katalogów».

Loevborg
źródło
no cóż, chciałem też znaleźć się ponownie we wszystkich podkatalogach, ale dzięki temu informacje są przydatne, zbyt często spotykam się z tą sytuacją :)
Bunny Rabbit
W rzeczywistości find nie jest do tego przesadą, globbing wybierze wszystkie dopasowania, nie tylko pliki, ale także katalogi. Jeśli masz obawy o wydajność, można również użyć coś takiego: find -type f -exec mv -t collection/ {} +. Sprawdź na stronie podręcznika, jak to działa.
Lekensteyn
Lekensteyn, masz rację. Zaktualizowałem odpowiedź, kiedy zrozumiałem pytanie.
loevborg
2
Cudowna odpowiedź, szkoda, że ​​nie dotyczy to w szczególności pytania :).
crazy2be