Cách di chuyển tất cả các tệp bao gồm các tệp ẩn vào thư mục mẹ qua *


113

Đó hẳn là một câu hỏi phổ biến nhưng tôi không thể tìm ra câu trả lời.

Cách di chuyển tất cả các tệp qua * bao gồm cả các tệp ẩn cũng như vào thư mục mẹ như sau:

mv /path/subfolder/* /path/

Thao tác này sẽ di chuyển tất cả các tệp vào thư mục mẹ như mong đợi nhưng sẽ không di chuyển các tệp ẩn. Làm thế nào để làm điều đó?


1
câu hỏi này có hai bản tại SU , với một câu trả lời thậm chí chính xác hơn (không phải là người chấp nhận mặc dù): cp -r /path/to/source/. /destination
Florian

Câu trả lời:


202

Bạn có thể tìm thấy một bộ giải pháp toàn diện về vấn đề này trong câu trả lời của UNIX & Linux cho Làm cách nào để di chuyển tất cả các tệp (kể cả ẩn) từ thư mục này sang thư mục khác? . Nó hiển thị các giải pháp trong Bash, zsh, ksh93, tiêu chuẩn (POSIX) sh, v.v.


Bạn có thể sử dụng hai lệnh này cùng nhau:

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

Hoặc tất cả cùng nhau ( cảm ơn pfnuesel ):

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

Mở rộng thành:

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

(ví dụ: echo a{.,}bmở rộng thành a.b ab)

Lưu ý rằng điều này sẽ hiển thị một số cảnh báo:

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

Chỉ cần bỏ qua chúng: điều này xảy ra bởi vì /path/subfolder/{.,}*cũng mở rộng đến /path/subfolder/./path/subfolder/.., là thư mục và thư mục mẹ (Xem “.” Và “..” có nghĩa là gì khi ở trong một thư mục? ).


Nếu bạn chỉ muốn sao chép, bạn có thể sử dụng:

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

Thao tác này sẽ sao chép tất cả các tệp, cả tệp bình thường và tệp ẩn, vì /path/subfolder/.mở rộng thành "mọi thứ từ thư mục này" (Nguồn: Làm thế nào để sao chép bằng cp để bao gồm tệp ẩn và thư mục ẩn và nội dung của chúng? )


2
Các dấu ngoặc nhọn chỉ là một đường tắt mv /path/subfolder/* /path/subfolder/.* /path/, không nhất thiết phải kết hợp hai lệnh thành một.
chepner

7
Tôi gặp lỗi sau: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 Chỉ cần bỏ qua nó. .biểu thị thư mục hiện tại và ..biểu thị upthư mục. Bạn phải nhận thấy rằng tất cả các tệp khác đã được di chuyển.
Debiprasad

Đáng nói rằng niềng răng Shortcut sẽ không làm việc cho tất cả vỏ, nhưng lệnh @chepner Tôi nghĩ rằng nó sẽ
Jesús Carrera

7
"Chỉ cần phớt lờ cảnh báo" có thể không phải lúc nào cũng là một ý kiến ​​hay. Hiện tại, tôi đang gặp sự cố với tập lệnh mà tôi cần dừng thực thi nếu bất kỳ bước nào không thành công - vì giải pháp này luôn gây ra lỗi, nó sẽ giết tập lệnh của tôi. Tôi cần một cách để xác định xem lệnh mv có bị lỗi hay không ...
MarioVilas

29

Tôi nghĩ đây là cách thanh lịch nhất, vì nó cũng không cố gắng di chuyển ..:

mv /source/path/{.[!.],}* /destination/path

1
vâng, tôi nhận thấy nó cũng đưa ra những thông báo lỗi đó, rất hay.
Joseph Astrahan

Tôi nghĩ rằng đây là một giải pháp rất tốt nhưng nó kinda khó nhớ rằng mẫu
Dylan B

điều này sẽ bỏ lỡ các tệp như ..anythinghoặc ...anythingv.v. - stackoverflow.com/a/31438355/2351568 chứa regex chính xác cho sự cố này. || nhưng dù sao sử dụng shopt -s dotglobvẫn là giải pháp tốt hơn!
DJCrashdummy

@DylanB đừng ghi nhớ nó. hãy nhớ rằng nó khớp với bất kỳ thứ gì trong dấu ngoặc nhọn, được phân tách bằng dấu phẩy. {a,b}*sẽ tìm thấy tất cả các tệp bắt đầu bằng a hoặc b, chẳng hạn như "giải phẫu" và "máy ủi". Trận đấu thứ hai chỉ là một trận đấu trống, tương đương với *và trận đấu đầu tiên tương đương với .[!.], trong đó nhóm [!.]có nghĩa là một nhóm KHÔNG bắt đầu bằng a .. Điều này có nghĩa là .*nhưng không ..*.
mazunki

28

Thao tác này sẽ di chuyển tất cả các tệp vào thư mục mẹ như mong đợi nhưng sẽ không di chuyển các tệp ẩn. Làm thế nào để làm điều đó?

Bạn có thể bật dotglob:

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

Để tắt dotglob, bạn cần nói:

shopt -u dotglob

Rất hữu ích. Muốn tìm hiểu thêm nhưng shopt là một bản dựng sẵn nên man shoptkhông hoạt động và help shoptrất ngắn gọn. Nhưng bạn có thể làm bashman () { man bash | less -p "^ $1 "; }và sau đó bashman shoptđọc tất cả về nó một cách đơn giản. (Có thể phải nhấn n để nhảy xuống lệnh nếu có dòng bắt đầu với shopt, như tôi đã được tìm thấy.)
Nick Rice

2
điều này cũng sẽ ảnh hưởng đến tất cả các lệnh khác như ls.. do đó không thực sự những gì bạn muốn, có lẽ
phil294

5

Giải pháp thay thế đơn giản hơn là sử dụng rsynctiện ích:

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

Lưu ý: Lệnh trên sẽ hiển thị những gì sẽ được thay đổi. Để thực hiện các thay đổi thực tế, hãy xóa--dry-run .

Ưu điểm là thư mục gốc ( subfolder) sẽ bị loại bỏ cũng như một phần của lệnh, và khi sử dụng các mvví dụ ở đây, bạn vẫn cần phải dọn dẹp các thư mục của mình, chưa kể phải đau đầu thêm để che các tệp ẩn và không ẩn trong một lần. mẫu.

Ngoài ra, rsynccung cấp hỗ trợ sao chép / di chuyển tệp giữa các điều khiển từ xa và nó sẽ đảm bảo rằng các tệp được sao chép chính xác như ban đầu ( -a).

-uTham số được sử dụng sẽ bỏ qua các tệp mới hơn hiện có, -rđệ quy vào các thư mục và -vsẽ làm tăng độ chi tiết.


Giải pháp tốt nhất bao giờ hết! Trong trường hợp của tôi, tôi chỉ xóa tham số -u, vì tôi không muốn cập nhật thư mục gốc. Cảm ơn
Thales Ceolin

Đây là một trong những lệnh mà nếu không cẩn thận, bạn thực sự có thể làm mọi thứ rối tung lên trong linux, vĩnh viễn. Vui lòng cập nhật câu trả lời của bạn để bao gồm sudo trước lệnh rsync, nếu không, người dùng có thể dễ dàng bị Từ chối Quyền đối với mkdir, nhưng việc xóa tệp sẽ vẫn tiếp tục, do đó, lệnh rsync sẽ xóa toàn bộ thư mục mà bạn muốn di chuyển và không làm gì khác . Bạn sẽ mất toàn bộ thư mục của mình. Khi bạn thêm sudo vào câu trả lời của mình, đây có thể là câu trả lời được chấp nhận. Vì vậy, lệnh phải là: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water

@JohnnyB Xin lỗi về sự bất tiện này. Tôi đã thêm sudo--dry-run, vì vậy mọi người có thể kiểm tra các thay đổi trước khi chạy lệnh thực sự để tránh bất kỳ sự lộn xộn tiềm ẩn nào.
kenorb

Ồ, tôi không nhận ra có một tùy chọn - chạy thử. Bổ sung tốt. Không cần lời xin lỗi. Thật tuyệt vời.
Blue Water

3

Hãy để tôi giới thiệu bạn với người bạn của tôi "dotglob". Nó bật và tắt cho dù "*" có bao gồm các tệp ẩn hay không.

$ 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

Nó mặc định là "tắt".

$ shopt dotglob
dotglob         off

Tốt nhất bạn nên bật lại khi làm xong nếu không bạn sẽ nhầm lẫn những thứ cho rằng nó sẽ tắt.


3

Bằng cách sử dụng findlệnh kết hợp với mvlệnh, bạn có thể ngăn mvlệnh cố gắng di chuyển các thư mục (ví dụ ...) và các thư mục con. Đây là một tùy chọn:

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

Có vấn đề với một số câu trả lời khác được cung cấp. Ví dụ: mỗi điều sau sẽ cố gắng di chuyển các thư mục con từ đường dẫn nguồn:

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

Ngoài ra, 2) bao gồm. và .. tệp và 3) bỏ lỡ các tệp như ..foobar, ... barfoo, v.v.

Bạn có thể sử dụng, mv /source/path/{.[!.],..?,}* /destination/pathbao gồm các tệp bị bỏ lỡ bởi 3), nhưng nó vẫn sẽ cố gắng di chuyển các thư mục con. Sử dụng findlệnh với mvlệnh như tôi mô tả ở trên loại bỏ tất cả các vấn đề này.


2

Giải pháp của tôi cho vấn đề này khi tôi phải sao chép tất cả các tệp (bao gồm cả .tệp) vào một thư mục đích giữ lại các quyền là: (ghi đè nếu đã tồn tại)

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

yeslà để tự động ghi đè tệp đích, rđệ quy, vdài dòng, pgiữ lại quyền.

Lưu ý rằng đường dẫn nguồn không kết thúc bằng a/ (vì vậy tất cả các tệp / thư mục và. Tệp đều được sao chép)

Thư mục đích kết thúc bằng/ khi chúng ta đang đặt nội dung của thư mục nguồn vào tổng thể đích.


Mặc dù yeslà một lệnh tuyệt vời để sử dụng nếu bạn muốn ghi đè các tệp đích, nhưng điều đó không phải lúc nào cũng mong muốn. Chỉ sử dụng nó nếu bạn chắc chắn muốn làm điều này. Ngoài ra, có sự khác biệt giữa yes | cp ...cp -f ...?
mazunki
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.