Làm cách nào để sao chép tệp có tên bắt đầu bằng dấu chấm?


26

Tôi đang cố gắng sao chép tất cả các tệp trong thư mục A sang thư mục B. Tất cả các tệp trong thư mục A đang bắt đầu bằng dấu chấm, ví dụ:

A/.a
A/.b
A/.c

mà tôi tìm thấy nếu tôi sử dụng : cp A/* B, luôn gặp lỗi:

cp: cannot stat 'A/*': no such file or directory

Dường như không có sự lựa chọn cho cplsđể xử lý các mục bắt đầu với dấu chấm, bất cứ ai có ý tưởng làm thế nào để sửa chữa nó?

Câu trả lời:


34

Lý do là bởi vì bash, *không bao gồm các tệp bắt đầu bằng dấu chấm ( .).

Bạn có thể chạy

cp A/.* B

Nó sẽ cảnh báo bạn rằng nó không sao chép .hoặc .., hoặc bất kỳ thư mục con nào, nhưng điều này là tốt.

Hoặc, nếu bạn muốn sao chép các tệp chấm và các tệp bình thường với nhau, hãy chạy

cp A/.* A/* B

Bạn cũng có thể chạy

shopt -s dotglob
cp A/* B

mà sẽ làm việc trong bash, nhưng không sh.

Và nếu bạn không nhớ các thư mục con cũng bị sao chép, thì đây là cách dễ nhất:

cp -R A/ B

Mẹo: Nếu bao giờ các ký tự đại diện không làm những gì bạn mong đợi, hãy thử chạy nó với echo, ví dụ:

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2

Đó chỉ là một vấn đề nếu bạn sử dụng -r. Nếu không -r, nó sẽ chỉ bỏ qua các thư mục.
Mikel

Và ví dụ tôi đưa ra sử dụng -Rcũng hoạt động tốt. Nếu bạn nghĩ nó sai, hãy giải thích tại sao.
Mikel

7

Nếu bash, bạn có thể đặt dotglobtrước khi sao chép

shopt -s dotglob
cp A/* /destination

Hoặc một ngôn ngữ lập trình

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Nếu bạn không muốn đặt dotglob, chỉ cần

cp A/.* /destination 2>/dev/null

Sử dụng dotglob OP cũng sẽ sao chép tất cả các tệp không bị ẩn, đây không phải là điều anh ấy muốn.
peoro

@peoro, bạn nên đọc lại câu hỏi. Tất cả các tập tin trong Ađược ẩn. Anh ta chỉ muốn sao chép điều đó.

7

Những gì bạn đang tìm kiếm là nhiều hơn dọc theo dòng:

cp A/.??* B/

Điều này sẽ phù hợp với tất cả các dotfiles, nhưng không phải "." hoặc là "..". Hầu hết các giải pháp trên đều ổn miễn là bạn không làm việc đệ quy. Nhưng ngay khi bạn muốn làm một cái gì đó như:

cp -R A/.??* B/

Không bỏ qua ".." bạn sẽ sao chép mọi thứ từ thư mục mẹ xuống, kể cả các tệp không phải là dấu chấm.


1
Điều này sẽ bỏ lỡ các tệp chấm là một ký tự đơn, như .ahoặc .x. Mẫu hình cầu ngắn nhất mà tôi đã tìm thấy khớp với mọi tệp chấm trừ ....[^.]*.
pavon

2

Tôi vừa thử những điều sau đây và nó hoạt động chỉ cần tìm ...

cp A/.* B/

2
Điều này cũng sẽ vượt qua A/.A/..như là các tham số cp, có thể có vấn đề trong trường hợp OP cũng cần sao chép thư mục (sử dụng cp -r)
peoro

2

Đó không phải cplỗi , đó là bash: bash mở rộng *trong tất cả các .tệp không bị ẩn (tức là: không bắt đầu bằng ).

Bash sẽ mở rộng .*(do đó A/.*, trong trường hợp của bạn) với tất cả các tệp bắt đầu ., nhưng thật không may, nó cũng bao gồm ...(thư mục hiện tại và thư mục gốc) mà bạn có thể sẽ muốn bỏ qua. (Lưu ý rằng các shell khác, như zsh, sẽ không bao gồm chúng và IIRC cũng bash, sau khi đặt một số tùy chọn).

Một giải pháp dễ dàng có thể là loại bỏ ...khỏi các tệp được khớp bởi .*, theo cách (rất) hacky như thế này:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

hoặc cái này (có thể sạch hơn: nó sử dụng findđể tìm các tệp cần sao chép):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

nhưng bạn có thể sẽ tìm thấy giải pháp sạch hơn.


Tại sao bạn nên sử dụng một for loopvà sau đó tạo thêm grepquy trình chỉ để thực hiện một công việc như thế cp A/.*nào? cpsẽ bỏ qua dấu "." và thư mục "..".

1

Nếu tất cả đều bắt đầu bằng dấu chấm, chỉ cần sử dụng A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

Hi vọng điêu nay co ich!


1

Bạn có thể sử dụng tập lệnh này

IFS = $ '\ n'; cho hành động bằng $ (tìm A -d 1); làm cp -R "$ hành động" B; làm xong


0

bản sao:

cp A/.* B

danh sách:

ls -l A/.*

liệt kê các tập tin mà không giảm các thư mục:

ls -ld A/.*

0

Bạn phải loại trừ. và .. từ danh sách tập tin được chuyển đến cp!

Điều này là an toàn:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B

0

Đây là một chủ đề cũ ... nhưng tôi luôn có thể sao chép tất cả các tệp. Bao gồm các tệp / thư mục bắt đầu bằng '.'

Ví dụ sẽ sao chép tất cả các tệp và thư mục:

cp -aup /root/.* / sao lưu / root /

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.