Jak przenieść wszystkie pliki, w tym pliki ukryte, do katalogu nadrzędnego za pomocą *

113

To musi być popularne pytanie, ale nie mogłem znaleźć odpowiedzi.

Jak przenieść wszystkie pliki przez *, w tym pliki ukryte, a także do katalogu nadrzędnego w następujący sposób:

mv /path/subfolder/* /path/

Spowoduje to przeniesienie wszystkich plików do katalogu nadrzędnego, zgodnie z oczekiwaniami, ale nie spowoduje przeniesienia plików ukrytych. Jak to zrobić?

TroodoN-Mike
źródło
1
to pytanie ma duplikat w SU , z jeszcze bardziej poprawną odpowiedzią (chociaż nie zaakceptowaną): cp -r /path/to/source/. /destination
Florian

Odpowiedzi:

202

Obszerny zestaw rozwiązań tego problemu można znaleźć w odpowiedzi na pytanie dotyczące systemów UNIX i Linux na temat: Jak przenieść wszystkie pliki (w tym ukryte) z jednego katalogu do drugiego? . Pokazuje rozwiązania w Bash, zsh, ksh93, standard (POSIX) sh itp.


Możesz używać tych dwóch poleceń razem:

mv /path/subfolder/* /path/   # your current approach
mv /path/subfolder/.* /path/  # this one for hidden files

Lub wszyscy razem ( dzięki pfnuesel ):

mv /path/subfolder/{.,}* /path/

Który rozszerza się do:

mv /path/subfolder/* /path/subfolder/.* /path/

(przykład: echo a{.,}brozwija się do a.b ab)

Zwróć uwagę, że spowoduje to wyświetlenie kilku ostrzeżeń:

mv: cannot move ‘/path/subfolder/.’ to /path/.’: Device or resource busy
mv: cannot remove /path/subfolder/..’: Is a directory

Po prostu je zignoruj: dzieje się tak, ponieważ /path/subfolder/{.,}*rozwija się również do /path/subfolder/.i /path/subfolder/.., które są katalogiem i katalogiem nadrzędnym (zobacz: Co oznaczają „.” I „..”, gdy znajdują się w folderze? ).


Jeśli chcesz po prostu skopiować, możesz użyć zwykłego:

cp -r /path/subfolder/. /path/
#                     ^
#                     note the dot!

Spowoduje to skopiowanie wszystkich plików, zarówno zwykłych, jak i ukrytych, ponieważ /path/subfolder/.rozwija się do „wszystkiego z tego katalogu” (Źródło: Jak skopiować za pomocą cp, aby uwzględnić ukryte pliki i ukryte katalogi oraz ich zawartość? )

fedorqui 'SO przestań szkodzić'
źródło
2
Nawiasy klamrowe to tylko skróty mv /path/subfolder/* /path/subfolder/.* /path/, które nie są niezbędne do łączenia dwóch poleceń w jedno.
chepner
7
Otrzymuję następujący błąd:mv: overwrite `/path/.'? y mv: cannot move `/path/subfolder/.' to `/path/.': Device or resource busy mv: overwrite `/path/..'? y mv: cannot move `/path/subfolder/..' to `/path/..': Device or resource busy
Dejan
@Dejan Po prostu zignoruj ​​to. .oznacza bieżący katalog i ..oznacza upkatalog. Musiałeś zauważyć, że wszystkie inne pliki zostały przeniesione.
Debiprasad
Warto wspomnieć, że skrót do nawiasów klamrowych nie będzie działał dla wszystkich powłok, ale polecenie @chepner myślę, że tak
Jesús Carrera
7
„Po prostu zignoruj ​​ostrzeżenie” nie zawsze jest dobrym pomysłem. W tej chwili mam problem ze skryptem, w którym muszę zatrzymać wykonywanie, jeśli jakikolwiek krok się nie powiedzie - ponieważ to rozwiązanie zawsze powoduje błąd, zabija mój skrypt. Potrzebuję sposobu, aby ustalić, czy polecenie mv zawiodło, czy nie ...
MarioVilas
29

Myślę, że jest to najbardziej eleganckie, ponieważ też nie próbuje się ruszać ..:

mv /source/path/{.[!.],}* /destination/path
Vanderstaaij
źródło
1
tak, zauważyłem, że podaje również te komunikaty o błędach, niezłe znalezisko.
Joseph Astrahan
Myślę, że to bardzo dobre rozwiązanie, ale trochę trudno zapamiętać ten wzór
Dylan B
to minie jak pliki ..anythinglub ...anythingitd. - stackoverflow.com/a/31438355/2351568 zawiera prawidłowy regex tego problemu. || ale tak czy inaczej, używanie shopt -s dotglobjest nadal lepszym rozwiązaniem!
DJCrashdummy
@DylanB nie zapamiętuj tego. pamiętaj, że pasuje do wszystkiego, co jest w nawiasach klamrowych, oddzielonych przecinkami. {a,b}*znajdzie wszystkie pliki zaczynające się od a lub b, na przykład „anatomia” i „buldożer”. Drugie dopasowanie jest po prostu pustym dopasowaniem, równoważne z *, a pierwsze dopasowanie jest równoważne .[!.], gdzie grupa [!.]oznacza grupę NIE rozpoczynającą się od .. To znaczy, .*ale nie ..*.
mazunki
28

Spowoduje to przeniesienie wszystkich plików do katalogu nadrzędnego, zgodnie z oczekiwaniami, ale nie spowoduje przeniesienia plików ukrytych. Jak to zrobić?

Możesz włączyć dotglob:

shopt -s dotglob               # This would cause mv below to match hidden files
mv /path/subfolder/* /path/

Aby wyłączyć dotglob, musisz powiedzieć:

shopt -u dotglob
devnull
źródło
Bardzo pomocne. Chciałem dowiedzieć się więcej, ale Shopt jest wbudowany, więc man shoptnie działa i help shoptjest bardzo krótki. Ale możesz to zrobić, bashman () { man bash | less -p "^ $1 "; }a potem bashman shoptprzeczytać wszystko na ten temat w prosty sposób. (Może być konieczne naciśnięcie n, aby przejść do polecenia, jeśli istnieją linie zaczynające się od shopt, jak znalazłem).
Nick Rice
2
wpłynie to również na wszystkie inne polecenia, takie jak ls... więc prawdopodobnie nie jest to, czego chcesz
phil294
5

Alternatywnym prostszym rozwiązaniem jest użycie rsyncnarzędzia:

sudo rsync -vuar --delete-after --dry-run path/subfolder/ path/

Uwaga: powyższe polecenie pokaże, co zostanie zmienione. Aby wprowadzić zmiany, usuń--dry-run .

Zaletą jest to, że oryginalny folder ( subfolder) zostałby usunięty, jak również część polecenia, a korzystając z mvprzykładów tutaj, nadal musisz wyczyścić foldery, nie wspominając o dodatkowym bólu głowy, aby ukryć ukryte i nieukryte pliki w jednym wzór.

Ponadto rsynczapewnia obsługę kopiowania / przenoszenia plików między pilotami i zapewnia, że ​​pliki są kopiowane dokładnie tak, jak były pierwotnie ( -a).

Użyty -uparametr pomija istniejące nowsze pliki, -rwraca do katalogów i -vzwiększa szczegółowość.

kenorb
źródło
Najlepsze rozwiązanie w historii! W moim przypadku właśnie usunąłem parametr -u, ponieważ nie chciałbym aktualizować folderu głównego. Dzięki
Thales Ceolin
Jest to jedno z tych poleceń, w przypadku których jeśli nie jesteś ostrożny, możesz naprawdę zepsuć sobie rzeczy w systemie Linux, na stałe. Zaktualizuj swoją odpowiedź, aby zawierała sudo przed poleceniem rsync, w przeciwnym razie użytkownicy mogą łatwo uzyskać odmowę uprawnień dla mkdir, ale usuwanie plików mimo wszystko pójdzie dalej, dlatego polecenie rsync usunie cały katalog, który chcesz przenieść, i nie zrobi nic więcej . Stracisz cały katalog. Gdy dodasz sudo do swojej odpowiedzi, prawdopodobnie powinna to być zaakceptowana odpowiedź. Więc polecenie powinno brzmieć: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water
@JohnnyB Przepraszamy za niedogodności. Dodałem sudoi --dry-run, aby ludzie mogli przetestować zmiany przed uruchomieniem rzeczywistego polecenia, aby uniknąć potencjalnego bałaganu.
kenorb
Och, nie zdawałem sobie sprawy, że istnieje opcja --dry-run. Dobry dodatek. Nie ma potrzeby przepraszania. To jest wspaniałe.
Blue Water
3

Pozwól, że przedstawię cię mojemu przyjacielowi „dotglob”. Włącza się i wyłącza niezależnie od tego, czy „*” obejmuje ukryte pliki.

$ mkdir test
$ cd test
$ touch a b c .hidden .hi .den
$ ls -a
. ..  .den  .hi .hidden a b c

$ shopt -u dotglob
$ ls *
a b c
$ for i in * ; do echo I found: $i ; done
I found: a
I found: b
I found: c

$ shopt -s dotglob
$ ls *
.den  .hi .hidden a b c
$ for i in * ; do echo I found: $i ; done
I found: .den
I found: .hi
I found: .hidden
I found: a
I found: b
I found: c

Domyślnie jest wyłączone.

$ shopt dotglob
dotglob         off

Najlepiej włączyć go ponownie, gdy skończysz, w przeciwnym razie pomieszasz rzeczy, które zakładają, że będzie wyłączone.

TomOnTime
źródło
3

Używając findpolecenia w połączeniu z mvpoleceniem, możesz uniemożliwić mvpoleceniu próby przeniesienia katalogów (np. ..I .) oraz podkatalogów. Oto jedna opcja:

find /path/subfolder -maxdepth 1 -type f -name '*' -exec mv -n {} /path \;

Istnieją problemy z niektórymi innymi udzielonymi odpowiedziami. Na przykład każdy z poniższych spróbuje przenieść podkatalogi ze ścieżki źródłowej:

1) mv /path/subfolder/* /path/ ; mv /path/subfolder/.* /path/
2) mv /path/subfolder/{.,}* /path/ 
3) mv /source/path/{.[!.],}* /destination/path

Ponadto 2) zawiera. i ... oraz 3) pomija pliki takie jak ..foobar, ... barfoo itp.

Mógłbyś użyć, mv /source/path/{.[!.],..?,}* /destination/pathktóry obejmowałby pliki pominięte przez 3), ale nadal próbowałby przenieść podkatalogi. Użycie findpolecenia z mvpoleceniem, jak opisałem powyżej, eliminuje wszystkie te problemy.

teancum144
źródło
2

Moje rozwiązanie tego problemu, gdy muszę skopiować wszystkie pliki (w tym .pliki) do katalogu docelowego, zachowując uprawnienia, to: (nadpisz, jeśli już istnieją)

yes | cp -rvp /source/directory /destination/directory/

yessłuży do automatycznego nadpisywania plików docelowych, rrekurencji, vrozwlekania, pzachowywania uprawnień.

Zwróć uwagę, że ścieżka źródłowa nie kończy się na/ (więc wszystkie pliki / katalog i. Pliki są kopiowane)

Katalog docelowy kończy się na,/ ponieważ umieszczamy zawartość folderu źródłowego w miejscu docelowym jako całości.

Rajneesh Gadge
źródło
Chociaż yesjest to niesamowite polecenie, jeśli chcesz zastąpić pliki docelowe, nie zawsze jest to pożądane. Używaj go tylko wtedy, gdy jesteś pewien, że chcesz to zrobić. Czy istnieje różnica między yes | cp ...i cp -f ...?
mazunki