Przenieś wszystkie pliki oprócz jednego

155

Jak mogę przenieść wszystkie pliki oprócz jednego? Szukam czegoś takiego:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

gdzie przenoszę stare rzeczy do nowego folderu z wyjątkiem Tux.png. ! -znak reprezentuje negację. Czy jest jakieś narzędzie do tej pracy?

Léo Léopold Hertz 준영
źródło

Odpowiedzi:

142

Jeśli używasz basha i masz extglobustawioną opcję powłoki (co zwykle ma miejsce):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/
sth
źródło
1
Wystąpił błąd, gdy przetestowałem polecenie dla wielu pozycji: mv ~ / Linux / Old /! (Tux.png Tux1.png Tux2.png) ~ / Linux / New / Opróżnia cały stary katalog. Co jest nie tak?
Léo Léopold Hertz 준영
5
@UnixBasics, spróbuj: ~ / Linux / Old /! (Tux.png | Tux1.png | Tux2.png)
Juliano
@Juliano Bardzo fajne polecenie! Czy jest więcej operacji matematycznych, takich jak OR i XOR? Zakładam, że fajka jest dla AND.
Léo Léopold Hertz 준영
@Juliano Jestem raczej zdezorientowany wzorcami takimi jak: mv ~ / Linux /? (Tux * .png) ~ / Linux / New / mv ~ / Linux / + (Tux * .png) ~ / Linux / New / W pierwszym , Chciałem przenieść 0-1 Tux - zdjęcie. W tym drugim przypadku chciałem przenieść zdjęcia 1-n Tux. Poruszyli wszystko. Czemu? Czy można przenieść określoną ilość zdjęć?
Léo Léopold Hertz 준영
97

Umieść następujący plik w swoim .bashrc

shopt -s extglob

Rozszerza wyrażenia regularne. Następnie możesz przenieść wszystkie pliki oprócz jednego o

mv !(fileOne) ~/path/newFolder

Wyjątki w stosunku do innych poleceń

Zauważ, że podczas kopiowania katalogów, forward-flash nie może być użyty w nazwie, jak zauważono w wątku. Dlaczego extglob oprócz łamania oprócz warunku? :

cp -r !(Backups.backupdb) /home/masi/Documents/

więc Backups.backupdb/jest źle tutaj przed negacją i nie użyłbym go również do przenoszenia katalogów ze względu na ryzyko niewłaściwego użycia then globs z innymi poleceniami i możliwymi innymi wyjątkami.

Léo Léopold Hertz 준영
źródło
3
To jest właściwie prawidłowa odpowiedź. Mój był całkowicie zły; na szczęście użyłem go w folderze zawierającym tylko kilka plików. Tutaj jest więcej informacji o metodzie, którą pokazuje Masi: wiki.bash-hackers.org/syntax/pattern Przejdź do "Rozszerzony język wzorców", a znajdziesz więcej informacji na ten temat. Podziękowania dla @ paul-whittaker za wskazanie problemu.
mimoralea
To stara odpowiedź, ale wciąż aktualna. Używam Ubuntu 18 i wydaje się, że extglob jest domyślnie włączony (nie kupowałem tego). Użyłem następującego polecenia, aby przenieść wszystkie pliki z bieżącego katalogu do archiwum, które również znajduje się w tym katalogu, BEZ innych folderów archiwum: mv !(arc*) archive_190629b
TonyG
70

Wybrałbym tradycyjny sposób znajdowania i xargs:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1sprawia, że ​​nie przeszukuje rekurencyjnie. Jeśli zależy Ci tylko na plikach, możesz powiedzieć -type f. -mindepth 1sprawia, że ​​nie zawiera ~/Linux/Oldsamej ścieżki w wyniku. Działa z dowolnymi nazwami plików, w tym z tymi, które zawierają osadzone znaki nowej linii.

Jeden komentarz wskazuje, że -topcja mv jest prawdopodobnie rozszerzeniem GNU. W przypadku systemów, które go nie mają

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;
Johannes Schaub - litb
źródło
1
Za uznaniem, ponieważ zachęca do nauki potężnego narzędzia, znajdź. Uwaga, dla plików z białymi znakami to nie zadziała. Rozważ "find -print0 | xargs -0" albo zrezygnuj z xargs: "znajdź [co powiedziałeś] -exec mv -t {} ~ / Linux / New \;"
JasonSmith
Jeśli twoje polecenie mv nie ma opcji -t, użyj "find ... -exec mv {} Linux / New \;" lub „find ... | xargs -I {} mv {} Linux / New”. Opcja -t wydaje się być rozszerzeniem GNU, które jest dobre dla Linuksa, ale prawdopodobnie nie gdzie indziej.
Rob Kennedy
jhs, och, zawodzę. jakoś pomyślałem, że xargs dzieli się na nowej linii, ale nie na spacjach. wygląda na to, że pomyliłem to z „czytaj” :) źle to napraw
Johannes Schaub - litb
Wielkie dzięki za niesamowitą wskazówkę! Miałem zamiar wybrać coś, ponieważ dotyczy tego pytania. Jednak później mogę wyczuć przydatność twoich poleceń, więc muszę wybrać sposób „znajdź i xargs”. Po prostu rządzi. Dzięki :)
Léo Léopold Hertz 준영
Zbyt skomplikowane. Odpowiedź Masi jest bardziej kompletna, łatwiejsza, a tym samym bardziej poprawna
user637338
30

Szybkim sposobem byłoby zmodyfikowanie nazwy pliku tux, aby polecenie ruchu nie pasowało.

Na przykład:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png
John T.
źródło
nie używaj „ . ”, ponieważ spowoduje to przeniesienie tylko plików, które mają „.” w imieniu. Wystarczy „*”.
Juliano
1
Jeśli zmienisz go na *, usunie to również plik, którego nazwa została zmieniona.
John T
6
@John T: Nie, * glob nie pasuje do plików zaczynających się kropką.
Bill Karwin
To zdecydowanie najlepsza odpowiedź. Nie musisz zmieniać ani komentować tej odpowiedzi. 100 punktów. Wielkie dzięki. Dobra robota!
Steve K
23

Myślę, że najłatwiej to zrobić za pomocą graweru

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Edytować:

Zamiast tego użyj odwrotnego ukośnika z ls, aby zapobiec używaniu go z aliasem, np. Większość ls jest aliasowana jako ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Dzięki @Arnold Roa

Rohail Abbas
źródło
1
Czy możesz wyjaśnić, dlaczego grep -vtam używasz ?
Léo Léopold Hertz 준영
1
-v opcja w grep wyklucza wynik, to tak, jakby wziąć wszystko oprócz Tux.png
Rohail Abbas
1
Jest to z pewnością intuicyjne, ale powyższe odpowiedzi są lepsze. Jeśli na przykład piszesz skrypt, wymagałoby to umieszczenia we właściwym katalogu ..
nJGL
@nJGL Możemy również podać tutaj absolutną ścieżkę, użyłem
katalogu głównego
@RohailAbbas W porządku. ✌️
nJGL
14

Dla bash, sth odpowiedź jest poprawna. Oto składnia zsh (moja wybrana powłoka):

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Wymaga ustawienia EXTENDED_GLOBopcji powłoki.

Juliano
źródło
3
A co, jeśli chcemy wykluczyć dwa pliki?
mpen
13

Uważam, że jest to nieco bezpieczniejsze i łatwiejsze do oparcia w przypadku prostych ruchów, które wykluczają określone pliki lub katalogi.

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET
alex.pilon
źródło
To najlepsze rozwiązanie dla Busybox / ASH
Stuart Cardall
1
To zadziałało dla mnie w sytuacji, gdy musiałem przenieść wszystkie pliki oprócz kilku folderów do innego katalogu
Umar Hayat
-lOpcja lsbędzie zawierać wiele nieistotnych informacji w linii poleceń i spowodować niepowodzenie polecenia mv.
jdhao
5

Poniższa metoda nie jest metodą gwarantowaną w 100% i nie należy jej w ogóle podejmować w przypadku skryptów. Ale czasami wystarczy do szybkiego użycia powłoki interaktywnej. Plik glob, taki jak

[abc]*

(który dopasuje wszystkie pliki o nazwach zaczynających się od a, b lub c) można zanegować, wstawiając najpierw znak „^”, tj.

[^abc]*

Czasami używam tego, aby nie dopasować katalogu „lost + found”, na przykład:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Oczywiście, jeśli są inne pliki zaczynające się od l, muszę je później przetworzyć.

hlovdal
źródło
4
mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

Polecenie find wyświetla listę wszystkich zwykłych plików, a polecenie fgrep odfiltrowuje wszystkie pliki Tux.png. Backticks mówią mv, aby przenieść wynikową listę plików.

David Norman
źródło
4
Nigdy, przenigdy nie oceniaj find jako argumentów dla innego polecenia. Zdarzą się złe rzeczy. Być może właśnie stworzyłeś lukę. Zawsze używaj polecenia find -print0 | xargs -0 konstrukcja lub znajdź -exec.
Juliano
3

Co powiesz na przeniesienie wszystkiego w folderze, a następnie przeniesienie pliku Tux.png z powrotem?

Nie przychodzi mi do głowy żadna składnia powłoki, która mogłaby powiedzieć „wszystko oprócz…” od ręki.

David Z
źródło
3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'
aitor
źródło
1
Wydaje się, że w tym poleceniu brakuje jednej części i nie działa na moim komputerze. ls ~/Linux/Old/ | grep -v Tux.png | xargs -I{} mv {} ~/Linux/New/zamiast tego działa.
Katherine Chen
3

Co powiesz na:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

Musisz jednak być w folderze.

antybus
źródło
3

Można pominąć grep w ten sposób:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/
Arch Linux Tux
źródło
1

To mogłoby być prostsze i łatwe do zapamiętania i działa dla mnie.

mv $(ls ~/folder | grep -v ~/folder/exclude.png) ~/destination

Pakpoom Tiwakornkit
źródło