Przenieś każdy plik, który nie jest katalogiem


14

Mam katalog, który próbuję wyczyścić, zawierający zarówno pliki, jak i podkatalogi. To, co próbuję zrobić, jest proste: przenieś wszystkie pliki do innego katalogu, ale pozostaw wszystkie podkatalogi bez zmian.

Mam na myśli coś takiego:

mv [*_but_no_dirs] ./other_directory

Wydaje się, że powinien istnieć prosty sposób na zrobienie tego za pomocą symboli wieloznacznych *i wyrażeń regularnych ...

Czy ktoś ma pomysły?


1
Więc przenieść wszystkie pliki do podfolderu, ale zignorować jakiś z podkatalogów?
Wilf

@Wilf: Dokładnie.
zapytania

2
W Zsh możesz to zrobić mv **/*(.) ./other_directory- za pomocą bash musisz jednak uciekać się do zewnętrznych poleceń, takich jak find.
godlygeek

Odpowiedzi:


12

Regex nie jest tutaj zaangażowany. Symbole wieloznaczne w bash (podobnie jak większość innych powłok) pasują tylko do plików na podstawie nazw plików, a nie na podstawie typu pliku lub innych cech. Istnieje jeden sposób dopasowania według typu: dodanie /na końcu wzorca powoduje, że dopasowuje tylko katalogi lub dowiązania symboliczne do katalogów. W ten sposób możesz przenosić katalogi, a następnie przesuwać to, co zostało, i przenosić katalogi z powrotem - kłopotliwe, ale działa.

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * "$tmp"/other_directory/
mv "$tmp"/* .
rmdir "$tmp"

Standardowym sposobem dopasowania plików według typu jest wywołanie find.

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +

W zsh możesz używać kwalifikatorów glob, aby dopasowywać pliki według typu. .Kwalifikator mecze zwykłe pliki; służy ^/do dopasowania wszystkich katalogów niebędących katalogami lub -^/do dołączenia symbolicznych łączy do katalogów.

mv -- *(.) other_directory/

W dowolnej powłoce możesz po prostu zapętlić.

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done

8

Możesz użyć czegoś takiego

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;

Najpierw używamy finddo wyszukiwania tylko w bieżącym directoy, następnie ignorujemy katalogi, używając w ! -type d końcu wykonujemy shi przenosimy wszystko do katalogu docelowego. Możesz spróbować {} +na końcu, który będzie szybszy.


2
Trochę wyjaśnienia, proszę ...
zapytania

1
@Questionmark Zaktualizowałem odpowiedź i dodałem wyjaśnienie. Warto także odwiedzić mywiki.wooledge.org/UsingFind
Valentin Bajrami

Dlaczego -exec sh -c 'mv "$@" MYDIR' _ {} \;raczej sugerujesz niż -exec mv {} MYDIR \;? Wystarczy, aby uzyskać coś, co może być usprawnione poprzez zmianę \;Do +? Możesz to zrobić za pomocą -exec mv -t MYDIR {} +formularza.
Scott

@Scott Nie miałem pojęcia o -tfladze. Wyjaśniłem również w odpowiedzi, że +jest szybszy, ale nie wszystkie findwersje go obsługują. Tak więc powyższy kod jest w zasadzie kompatybilny z dowolnym findlub używaną powłoką.
Valentin Bajrami

1
@ val0x00ff: „… powyższy kod jest w zasadzie kompatybilny z dowolną findużywaną powłoką.” To prawda, ale tak jest find … -exec mv {} MYDIR \;i zużywa mniej zasobów niż … -exec sh -c 'mv "$@" MYDIR' _ {} \;.
Scott

0

Jest to potencjalnie trochę niebezpieczne, ale

cp * destination/
rm *

Ponieważ zarówno cp, jak i rm nie będą działać na katalogach bez przełącznika -r.


-1

Sugerowałbym po prostu zrobić mv *.* destination/z miejscem docelowym / folderem, do którego się przeprowadzasz.



2
Nazwy katalogów mogą zawierać „kropkę”, a nazwy plików mogą je wykluczać (i często tak robią), więc *.*przenoszą niektóre katalogi i pozostawiają niektóre pliki, czego nie chciał pytający.
dave_thompson_085

Przepraszam, ale to całkowicie źle. Po prostu poruszy wszystko z kropką w nazwie i nie poruszy niczego bez niej. Kropki nie są w żaden sposób wyłączne dla plików i nie są również wymagane przez pliki, więc to po prostu przeniesie losowy wybór plików i katalogów.
terdon

-2
mv $(ls -l | grep "^-" | awk '{print $9}') ./folder_where_move
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.