Làm cách nào tôi có thể lấy mv (hoặc ký tự đại diện) để di chuyển các tệp bị ẩn?


133

Tôi đang di chuyển thư mục nhà của mình từ một hệ thống cũ sang một hệ thống mới và tarball tôi tạo có chứa mọi thứ, bao gồm các tệp ẩn như .bashrc. Tuy nhiên, khi tôi di chuyển nội dung của tarball đã giải nén (nằm trong / tmp) sang thư mục chính mới của tôi, các tệp ẩn không sao chép ( mv /tmp/home/rcook/* /home/rcook/). Làm thế nào tôi có thể nhận được mv để di chuyển chúng?

Trên thực tế, tôi nghĩ rằng vấn đề không nằm ở mv, mà là vấn đề toàn cầu của bash. Nếu tôi làm điều này:

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/

Tôi thấy điều này:

a/:
.  ..  .foo

b/:
.  ..  bar

a/.fookhông di chuyển. Vậy làm thế nào tôi có thể lấy * ký tự đại diện để tìm các tập tin ẩn?

Có, tôi cho rằng tôi có thể giải nén tarball trực tiếp vào thư mục nhà của mình, nhưng tarball giải nén vào home/rcook/...và tôi muốn chắc chắn rằng tôi đã ghi đè lên bản mới .bashrc, v.v. bằng các phiên bản cũ, tùy chỉnh và biết cách tìm và di chuyển các tệp ẩn là một kỹ năng đáng giá. Gợi ý?


Một số câu trả lời đề nghị làm một cái gì đó như mv src/.* dest/. Tuy nhiên, tôi đã thử điều này trên các thư mục thử nghiệm của tôi và đã gặp lỗi. Bắt đầu với:

rcook$ ls -a a/ b/
a/:
.  ..  bar  .foo

b/:
.  ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
.  ..  bar

b/:
.  ..  .foo

Tôi đang làm gì sai?


Câu trả lời:


146

Bạn có thể làm được việc này :

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/

Bạn có thể đặt

shopt -s dotglob

trong của bạn ~/.bashrcnếu bạn muốn nó là mặc định.

Xem http://mywiki.wooledge.org/glob


Một cách tiếp cận khác để sao chép các tập tin dấu chấm:

mv /tmp/home/rcook/.[!.]* /home/rcook/

Không sử dụng mẫu ..*khi nó khớp ..(con trỏ tới thư mục cha). Nếu có các tệp có tên bắt đầu bằng hai dấu chấm ( ..something), cũng sử dụng mẫu ..?*.


Vui lòng kiểm tra các bổ sung tôi đặt ở dưới cùng của câu hỏi của tôi. Cảm ơn.
Randall Cook

1
Nothings sai, ...các thư mục đặc biệt: thư mục hiện tạithư mục gốc . Đó chỉ là một cảnh báo. shopt -s dotglobGiải pháp sử dụng tốt hơn
Gilles Quenot

Tôi cuối cùng chỉ làm hai động tác: mv home/rcook/* /home/rcook/tiếp theo mv home/rcook/.* /home/rcook/. Điều này đã tạo ra mánh khóe, mặc dù tôi ước rằng tôi đã theo liên kết và đọc về chế độ dotglob trước. Nó sẽ giúp tôi tiết kiệm một bước. +1
Randall Cook

Vậy cách tiếp cận thứ hai đòi hỏi phải sử dụng đường dẫn tuyệt đối?
franzlorenzon

3
Nếu bạn đang sử dụng zsh, bạn có thể sử dụng các Dvòng loại globbing hoặc các GLOB_DOTStùy chọn vỏ .
mgasms

43

Trong phần bổ sung của bạn, bạn có lỗi nhưng mã vẫn hoạt động. Điều duy nhất cần thêm là bạn nói nó chỉ để sao chép các tập tin dấu chấm. Thử:

mv src/* src/.* dst/

Bạn vẫn sẽ nhận được các lỗi cho. và .. mục, đó là tốt. Nhưng di chuyển nên thành công.

~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move from/.’ to to/.’: Device or resource busy
mv: cannot remove from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
.  ..

to/:
.  ..  test  .test

1
Điểm tốt, @AndrewSchwartz. Tôi cũng thích cách tiếp cận này. Tôi nghĩ rằng nó xứng đáng được công nhận nhiều hơn.
Randall Cook

Tôi thích @Drake Clarris trả lời thêm một chút, vì tôi đang chạy trên Amazon AWS CodeBuild và mã trả về không bằng 0 thực sự khiến quá trình xây dựng của tôi bị dừng. Cuối cùng tôi đã chuyển một .hiddentập tin mà tôi có để giải quyết vấn đề của mình.
HeyWatch This

Nếu mã thoát không bằng 0 là một vấn đề bạn có thể loại bỏ nó, ví dụ bằng cách nối thêm || :( ||có nghĩa là thực thi lệnh sau trên false / error, :là lệnh noop). Nhưng điều đó cũng sẽ ngăn chặn các lỗi hợp pháp, ví dụ thư mục đích không tồn tại. Tôi không thể tìm thấy một cách thanh lịch hơn bằng cách sử dụng mvđể loại trừ các mục .... Điểm cộng lớn đối với tôi qua cp là không ghi tập tin mới vào đĩa.
Andrew Schwartz

10

Nếu bạn ls -ltrong một thư mục, bạn sẽ thấy ...trong số các tệp được liệt kê. Vì vậy, tôi nghĩ rằng mv .* /destcó những con trỏ vào tài khoản. Thử:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

điều này sẽ bỏ qua những con trỏ dir hiện tại và cha mẹ.

Bạn sẽ nhận được một lỗi nếu bất kỳ một trong ba mẫu *, [^.]*hoặc ..?*không khớp với tập tin, vì vậy bạn chỉ nên bao gồm những người phù hợp.


Đẹp. Một câu trả lời tương tự cho phong cách toàn cầu này là ở đây: superuser.com/a/784046/144977 . Cảm ơn đã đăng bài này.
phyatt

7

Hai giải pháp có thể tôi có thể nghĩ ra. Đầu tiên là sử dụng cp thay vì với tùy chọn đệ quy của nó, sao chép thư mục hiện tại đến đích.

cp -Rp . /desired/directory

sau đó bạn có thể loại bỏ các tệp nguồn trong thư mục hiện tại

Ngoài ra, nếu bạn biết các tệp được đặt tên hoàn toàn (không có dấu cách, ký tự đại diện, ký tự không in được), bạn có thể làm một cái gì đó như thế này

mv $(ls -A) /desired/directory

4
Copy-then-remove rất khác so với di chuyển nếu nguồn và đích nằm trên cùng một hệ thống tệp. Ít nhất bao gồm tùy chọn -pđể bảo tồn siêu dữ liệu. Sử dụng lsnên là phương sách cuối cùng, và ở đây có những cách tốt hơn, đơn giản hơn.
Gilles

2

Thực sự không có thứ gọi là tệp "ẩn" trên Linux. Các tệp bắt đầu bằng dấu chấm chỉ được ẩn khỏi danh sách tệp theo mặc định.

Để sao chép các tập tin ngay cả với một glob, bạn cần phải thêm tiền tố file với .như mv -u .* foovà sau đó .foosẽ appearn như foo/.fookhi di chuyển.

Tùy chọn -u sẽ chỉ di chuyển các tệp khi nguồn mới hơn hoặc thiếu đích. Hoặc bạn có thể bỏ qua các lỗi về việc di chuyển ...vì chúng là các tệp đặc biệt và không thể di chuyển được, nhưng bị kẹt trong toàn .*cầu bởi trình bao.


Vui lòng kiểm tra các bổ sung tôi đặt ở dưới cùng của câu hỏi của tôi. Cảm ơn.
Randall Cook

0

Vì vậy chúng tôi có:

a
|-- .foo
`-- bar

và:

b

Tôi đã mất một thời gian lớn để tìm giải pháp tốt hơn tất cả các câu trả lời ở đây.

Sau đó tôi mất 30 giây cho lệnh này:

$ mv --help

Rồi tôi tìm thấy tình yêu của mình:

$ mv a/ b/ -T

Lưu ý: Tôi thậm chí không hiểu đối số -T. Nó chỉ làm những gì tôi cần. Ở đây nó nói:

-T, --no-target-thư mục coi DEST như một tệp bình thường


1
Nếu bạn bỏ qua dấu gạch chéo, bạn không cần -T. Dù bằng cách nào thì điều này về cơ bản là bảo mv tự di chuyển thư mục, thay vì di chuyển tất cả các tệp từ bên trong nó.
thomasrutter

@thomasrutter, không phải việc di chuyển thư mục giống như đổi tên nó sao?
Randall Cook

3
Có, nếu đích đến vẫn giữ nguyên, về cơ bản, nó chỉ đổi tên nó. Tuy nhiên, bạn đề cập đến nó, có lẽ nó không giúp trả lời câu hỏi ban đầu, đó là về việc di chuyển các tệp trong thư mục vào một vị trí nhất định.
thomasrutter

0

Trong trường hợp của tôi, tôi chỉ đơn giản là cố gắng để mvmột tập tin ẩn duy nhất và đây là giải pháp:

FILE=.myHiddenFile
mv "$FILE" dest/

Giải trình

Lúc đầu tôi đã thử:

mv .myHiddenFile dest/

Nhưng nó tiếp tục tạo ra lỗi:

mv: cannot stat '.myHiddenFile': No such file or directory

Mặc dù một ls -alcho thấy rằng các tập tin và dest/tồn tại.

Lý do có vẻ là vì shell đã diễn giải "." trong tên tệp, do đó, bằng cách di chuyển nó đến một biến, nó tránh được việc giải thích. Có lẽ có nhiều cách khác để giải quyết vấn đề này, nhưng điều này là đủ cho chúng tôi.


-1

Nếu bạn muốn sao chép các tập tin bao gồm các tập tin ẩn vào thư mục hiện tại mà bạn đang ở.

cp -Rp source-directory/. .

1
Điều này rất giống với câu trả lời của Drake Clarris từ năm 2013. Bạn có thêm gì nữa không?
Randall Cook
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.