Jak przenieść wszystkie pliki z bieżącego katalogu do wyższego katalogu?


133

Jak przenieść wszystkie pliki z bieżącego katalogu do katalogu wyższego w systemie Linux?

Próbowałem czegoś takiego mv *.*, ale to nie działa.


Nie mam wystarczającej liczby przedstawicieli, aby ponownie oznaczyć pytania, ale czy mogę zasugerować [linux] [mv] [cwd] [files]coś podobnego?
Stephan202

Poprawiłem to pytanie zgodnie z prośbą Stephan202.
jedenaście81

Odpowiedzi:


202

Polecenie, którego szukasz, to

mv * .[^.]* ..

lub (więcej informacji poniżej):

(shopt -s dotglob; mv -- * ..)

Objaśnienie: mvpolecenie przenosi pliki i katalogi. Ostatnim argumentem mvjest cel (w tym przypadku katalog jeden krok „w górę” w drzewie, ..). Argumenty poprzedzające to pliki źródłowe i katalogi. Gwiazdka ( *) to symbol wieloznaczny, który pasuje do wszystkich plików, które nie zaczynają się od kropki. Pliki zaczynające się od kropki (pliki kropkowe) są „ukryte”. Są one dopasowywane za pomocą wzorca .[^.]*(patrz edycja poniżej).

Aby uzyskać więcej informacji, zobacz stronę podręcznika, z którą się połączyłem mv.


Dlaczego .[^.]*zamiast .*?

Jak słusznie zauważa Chris Johnsen : wzór .*również pasuje .i ... Ponieważ nie chcesz (i nie możesz) przenieść ich, lepiej jest użyć wzorca, który pasuje do dowolnej nazwy pliku rozpoczynającej się od kropki oprócz tych dwóch . Wzór .[^.]*robi to tylko: pasuje do dowolnej nazwy pliku (1) zaczynającej się od kropki (2), po której następuje znak, który nie jest kropką (3), po której następuje zero lub więcej dowolnych znaków.

Jak wskazuje Paggas , musielibyśmy również dodać wzór , aby dopasować pliki zaczynające się od dwóch kropek. Zobacz jego odpowiedź na alternatywne rozwiązanie ..??*find

Odpowiedź Arjana wspomina shopt, aby uniknąć tych wszystkich problemów z plikami dot. Ale nadal występuje problem z plikami zaczynającymi się od myślnika. I wymaga trzech poleceń. Mimo to podoba mi się ten pomysł. Proponuję użyć tego w następujący sposób:

(shopt -s dotglob; mv -- * ..)

Wykonuje się to shoptw podpowłoce (a więc nie jest shoptwymagane drugie wywołanie ) i używa --, aby pliki zaczynające się od myślnika nie były interpretowane jako argumenty mv.


7
Użycie .*może spowodować, że mv wyświetli ostrzeżenia / błędy o niemożności poruszania się .i ... Zamiast mv * .[^.]* ..tego możesz spróbować .
Chris Johnsen

1
@alain: zapraszamy i witamy na stronie! (Jeśli (i tylko jeśli) jeden z postów dostatecznie odpowiedział na twoje pytanie, możesz oznaczyć je jako takie.
Otrzymasz

Naprawdę podoba mi się rozwiązanie shopt działające w podpowłoce :)
Paggas,

2
Składnia *. * Nie szkodzi - w tym .. jest niebezpieczna tylko w połączeniu z chmod i chown oraz flagą „recurse”, tj. Chmod -R lub chown -R. W takich przypadkach nigdy nie wpisuj chown. * Lub chmod. * - chown najwyższy katalog na ścieżce, której szukasz, i użyj opcji -h (nie podążaj za dowiązaniami symbolicznymi). Ale mv .. po prostu nic nie robi, więc nie martw się tym.
Chris

1
Poprawne są trzy wzory *, .[^.]*i ..?*. Drugi może .[!.]*dotyczy starszych (POSIX) powłok. Przeczytaj także

42

Krótka odpowiedź: użyj

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Długa odpowiedź:

Komenda

mv * .* ..

nie będzie działać, ponieważ .*można dopasować .i ... Ale polecenie

mv * .[^.]* ..

też nie będzie działać, ponieważ .[^.]*nie pasuje, np. ..filename! Zamiast tego robię to

mv * .[^.] .??* ..

który pasuje do wszystkiego oprócz .i ... *dopasuje wszystko, co nie zaczyna się od ., .[^.]dopasuje wszystkie 2-znakowe nazwy plików zaczynające się od kropki, z wyjątkiem .., i .??*dopasuje wszystkie nazwy plików rozpoczynające się od kropki z co najmniej 3 znakami.

Jeszcze lepiej, możesz użyć

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

co pozwala uniknąć brzydkich włamań do globu mv * .[^.] .??* ..!


1
Zapomniałem też o znaczeniu - aby polecenie działało poprawnie z nazwami plików rozpoczynającymi się od myślnika. Uwzględniłem - jednak w mojej znalezionej odpowiedzi. Bardziej kompletna odpowiedź przy użyciu globów to „mv - *. [^.]. ?? * ..”.
Paggas

+1: Wróciłem, aby dodać ..?*do mojego komentarza, a ty już się tym zająłeś.
Chris Johnsen

1
Co może być nie tak z próbą mv ..? Po prostu nic nie robi i nic nie może zrobić. Istnieją inne polecenia, w których można coś zrobić (chmod i chown), ale mv i rm po prostu nic nie robią. lub ..
Chris

1
To daje mv: nielegalną opcję - t
pal4life

1
Bono, podwójne myślniki każą mvprzestać szukać dalszych opcji poleceń. Nawiasy klamrowe to wynikowa nazwa pliku. Znak plus mówi, że zamiast uruchamiać exec na wynik (tj. Na nazwę pliku), umieść jak najwięcej wyników w jednym exec. Dla kompletności -t..mówi przeniesienie docelowego miejsca docelowego, aby przenieść wszystkie te pliki do.
isuldor

14

Ze względu na kompletność można również powiedzieć powłoce Bash, aby zawierała ukryte pliki, używając shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1. Dużo czystsze. Myślę jednak, że poprawa jest niewielka. Zobacz aktualizację mojej odpowiedzi.
Stephan202

8

Mv nie ma możliwości przenoszenia ukrytych plików podczas korzystania *- dlaczego więc nie użyć kopiowania?

cp -rf . ..

rm -rf *

Nie musisz wchodzić w złożone rozwiązania dotglobbingu i używania poleceń find.


Ostrzeżenie Jeśli poruszasz się w tym samym systemie plików , w większości przypadków tak naprawdę nie skopiowałeś plików, a jedynie zaktualizowałeś wpisy katalogu bez przenoszenia i-węzła lub zawartości pliku. Zobacz nawet [1 ]. Z cpa rmzamiast tego naprawdę kopiujesz wszystko.
Hastur

6
rsync -a --remove-source-files . ..

rsync to niezwykle potężne narzędzie do kopiowania plików, zwykle używane do wykonywania wydajnych przyrostowych zdalnych kopii zapasowych i kopii lustrzanych.

Za pomocą powyższego polecenia mówimy, rsyncaby skopiować zawartość .do..

Przełącznik -aumożliwia rekurencję do .podkatalogów i włącza inne popularne opcje.

Przełącznik --remove-source-filesinformuje rsync, aby usunął pliki źródłowe po udanej kopii, tzn. Powoduje, że rsync zachowuje się podobnie do mvpolecenia.


1
Przydałoby się trochę więcej wyjaśnień.
ChrisF,

Jasne, mam nadzieję, że teraz jest bardziej jasne.
mrucci

Pamiętaj, że --remove-source-filesnie usuniesz (zsynchronizowanych) katalogów.
Dennis

Ładne, zaakceptowane rozwiązanie daje mi -bash: /bin/mv: Argument list too longbłąd. Ten działa jak urok.
userlond

2

Ostatecznie próba mv .zakończy się niepowodzeniem, ponieważ mv nie będzie w stanie odłączyć katalogu, w którym aktualnie się znajdujesz. Możesz mv * ..przenieść pliki do cwd.


2
mv * .??* ../.

*pobiera wszystkie pliki bez kropek. .??*dostaje wszystko. pliki o długości co najmniej trzech bajtów, co działa dla wszystkich legalnych. Wszystko, co prawdopodobnie chcesz, rma nie mvtak.

../.Nie oferuje żadnych bezpośrednich korzyści nad ..ale kiedy robi przełączenia do katalogu jest to bardzo dobry zwyczaj, aby dostać się, bo to się nie uda, jak chcesz, jeśli coś jest nie tak ze ścieżką. Na przykład, mv xyz bletchjeśli uważasz , żebletch jest katalogiem, możesz być bardziej pewny dzięki mv xyz bletch/..


2
Możesz dodać, .[^.]aby uzyskać pliki okładki takie jak .a.
Chris Johnsen

Nie ma różnicy między ../ a ../. więc nie zawracałbym sobie głowy pisaniem. po cięciu. Ponadto, w przypadku mv i rm, włączenie nie ma żadnej szkody. i .. na liście, tj. nie ma nic strasznego lub złego w mv *. * / path / to / file /, podobnie jak rm. lub nawet -rf. nic nie robi
Chris

2

To zminimalizowane polecenie działa na większości nowoczesnych powłok:

\mv -- {,.{[^.],??}}* ..

W innym przypadku wymieniono przenośne rozwiązanie:

\mv -- * .[^.] .??* ..

Cechy:

  1. \ zapobiega niepożądanemu zmienianiu mv przez aliasy.

  2. - zapobiega interpretowaniu nazw plików zawierających wiodące łączniki (-xyz) jako argumentów wiersza poleceń.

  3. . [^.] pasuje do wszystkich dwóch nazw plików rozpoczynających się od. z wyjątkiem ..

  4. . ?? * pasuje do wszystkich innych nazw plików składających się z trzech lub więcej znaków.

Naiwne wdrożenia:

  1. Poniższe pomija ukryte nazwy plików UNIX, te zaczynające się od. (.bashrc).

    mv * ..
    
  2. Następujące dopasowania…, które rekurencyjnie próbują przenieść każdy katalog do końca z powrotem do / do… bieżącego katalogu roboczego ($ PWD lub pwd). Nigdy nie używaj.

    mv .* ..
    

2

Bardziej poprawne jest użycie wzorca * .[!.] .??*niż * .[^.] .??*ten pierwszy, który będzie działał również ze starszymi powłokami, takimi jak ksh88:

mv -- * .[!.] .??* ..
  • -- zapobiega problemom, gdy masz nazwę pliku, która zaczyna się od -
  • * pasuje do wszystkich nazw plików, które nie zaczynają się od .
  • nie ma nazw plików zawierających jeden znak, które zaczynają się od nazwy, którą .można / należy przenieść
  • .[!.] dopasowuje wszystkie dwie nazwy plików znaków rozpoczynające się od .
  • .??* pasuje do wszystkich trzech nazw plików (lub dłuższych), które zaczynają się od .

W przypadku ksh88 wzorzec nazw plików .[^.]w rzeczywistości będzie pasował do nazw plików ..(które zawsze istnieją) i .^(które prawdopodobnie nie istnieją), powodując efekt odwrotny do pożądanego.


0

Znajdź i grep też działają. Tego rodzaju struktura może być pomocna, jeśli chcesz wybrać pliki według bardziej skomplikowanych kryteriów, modyfikując find i egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

Myślę, że najłatwiejszym rozwiązaniem do przeniesienia wszystkich plików do katalogu nadrzędnego. byłoby

mv "`ls`" ../

lub Jeśli są ukryte pliki / katalogi

posługiwać się:

mv "`ls -a`" ../ 2>/dev/null

Powiedzmy też, że chcesz przenieść zawartość jakiegoś folderu do jednego z tony folderu wewnętrznego (powiedzmy)

posługiwać się:

mv "`ls -a`" /tony 2>/dev/null

Uwaga:

"`ls -a`" 

Aby przenieść pliki ze spacjami.

2>/dev/null

Czy dla tłumienia ostrzegawczy / błąd, ponieważ ls -abyłoby wydrukować .i ..folderów, jak również i nie można przenieść lub skopiować je. Więc dla tych folderów pokaże błąd (jeśli nie użyjemy 2> / dev / null), że nie może ich przenieść, a reszta zostanie przeniesiona całkiem wygodnie.

Najlepiej unikać, ls -ajeśli nie ma ukrytych plików i po prostu użyć ls.


Czy próbowałeś, co się stanie, gdy biegniesz mv $(ls -a)? To dotknęłoby bieżący katalog i katalog pod nim, ponieważ również ls -awyjdzie ...
Sami Laine,

Dzięki, @SamiLaine za sugestię, że wprowadziłem poprawki. Ale mv ls -a ../działałby również w razie potrzeby, tak, pokaże te błędy, jak wspomniałem powyżej, ale poza tym przeniesie wymagane foldery / pliki do katalogu nadrzędnego.
Prabhat Kumar Singh

To nie zadziała dla plików ze spacjami.
kenorb

@kenorb musisz dwukrotnie zacytować lspolecenie, aby przenieść pliki ze spacjami. Dokonałem wymaganych zmian. Dzięki za wskazanie.
Prabhat Kumar Singh,
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.