2012-05-05 29 views
17

Tôi muốn biết liệu rm có thể xóa tất cả các tệp trong thư mục (không phải thư mục con hoặc tệp trong thư mục con) không?Xóa tất cả các tệp trong thư mục (không chạm vào bất kỳ thư mục nào hoặc trong bất kỳ thư mục nào)

Tôi biết một số người sử dụng:

rm -f /direcname/*.* 

nhưng điều này giả định tên tập tin có phần mở rộng mà không phải tất cả làm (Tôi muốn tất cả các file - có hoặc không có một phần mở rộng phải được loại bỏ).

+0

là câu trả lời duy nhất? Tôi ngạc nhiên rằng rm không thể xử lý điều này mà không đưa ra cảnh báo vì nó có vẻ giống như một hoạt động đơn giản như vậy – toop

+1

có gì sai với 'find'? Tôi hiểu rằng nó có vẻ hơi clunky, nhưng tốt hơn nên giữ 'rm' đơn giản và' tìm' clunky hơn là yêu cầu mọi tính năng được thêm vào 'rm' (render nó giống như clunky như' find') – Shep

Trả lời

2

Bạn có thể sử dụng

find /direcname -maxdepth 1 -type f -exec rm -f {} \; 
+2

This -is - đã đệ quy, mà OP không muốn. – Jens

+0

Chắc chắn, tôi đã quên đối số maxdepth. Đã sửa. – tonio

7
find /direcname -maxdepth 1 -type f -exec rm {} \; 

Giải thích:

  • find tìm kiếm cho các tập tin và thư mục trong /direcname
  • -maxdepth hạn chế nó để tìm kiếm cho các tập tin và thư mục mà là con trực tiếp của /direcname
  • -type f hạn chế tìm kiếm đối với tệp
  • -exec rm {} \; chạy lệnh rm {} cho mỗi tệp (sau khi thay thế đường dẫn của tệp thay cho {}).
+0

cách tinh vi làm ot –

+1

bạn cũng có thể sử dụng '-delete' thay vì' -exec rm {} \; ' – Shep

+0

@Shep, yep, đó là tốt hơn. Mặc dù tôi nhận thấy xe đẩy sử dụng nó, vì vậy tôi sẽ để nó cho họ và sẽ không thay đổi câu trả lời của tôi. – huon

2

Một giải pháp vỏ (không có phi tiêu chuẩn tìm -maxdepth) sẽ là

for file in .* *; do 
    test -f "$file" && rm "$file" 
done 
+0

khoảng cách giữa 2 asterix có nghĩa là gì? – toop

+0

Trong một số hệ vỏ hoặc với một số thiết lập tham số nhất định, '*' không tạo tên tập tin bắt đầu bằng dấu chấm, do đó tôi yêu cầu rõ ràng tất cả '.profile', vv với'. * '. Sau đây '*' globs tất cả các tập tin khác. Nếu sau này cũng chứa các tập tin dấu chấm, điều này kết thúc với tên trùng lặp, đó là vô hại, như 'test -f' sau đó sẽ bỏ qua các tập tin đã bị loại bỏ. – Jens

33

Mặc dù tìm cho phép bạn xóa các tập tin sử dụng -exec rm {} \; bạn có thể sử dụng

find /direcname -maxdepth 1 -type f -delete 

và nó là nhanh hơn. Sử dụng -delete ngụ ý tùy chọn -depth, có nghĩa là nội dung thư mục quá trình trước thư mục.

+0

sử dụng '-delete' như trái ngược với '-exec' giữ một số trường hợp của rm khỏi bị đưa ra để xóa các tập tin tìm thấy bằng cách thực hiện ** tìm ** – user1055604

+0

Bạn đã có câu trả lời hữu ích nhất trên tất cả các interwebz: cổ vũ D! Nó làm cho ngày của tôi! –

+1

Sử dụng 'tìm. -maxdepth 1-type f -delete' nếu bạn đã có trong thư mục – babonk

1

Một số vỏ, đặc biệt là zsh và có lẽ bash phiên bản 4 (nhưng không phải phiên bản 3), có cú pháp để thực hiện điều đó.

Với zsh bạn có thể chỉ cần gõ

rm /dir/path/*(.) 

và nếu bạn muốn loại bỏ bất kỳ tập tin có tên bắt đầu với foo, đệ quy trong các thư mục con, bạn có thể làm

rm /dir/path/**/foo*(.) 

tính năng sao đôi là (với IMHO hoàn thành tương tác tốt hơn) theo ý kiến ​​của tôi đủ để chuyển sang zsh cho các trình bao tương tác. YMMV

Dấu chấm trong hậu tố dấu ngoặc đơn chỉ ra rằng bạn chỉ muốn các tệp (không phải là liên kết hoặc thư mục) mở rộng được mở rộng bởi vỏ zsh.

1

Unix không phải là DOS. Không có trường "mở rộng" đặc biệt trong tên tệp. Bất kỳ ký tự nào sau dấu chấm chỉ là một phần của tên và được gọi là hậu tố. Có thể có nhiều hơn một hậu tố, ví dụ: .tar.gz. Ký tự shell glob * đối sánh trên các ký tự .; nó là không biết đến hậu tố. Vì vậy, MS-DOS *.* chỉ là * Trong Unix.

Hầu như. * không khớp với tệp bắt đầu bằng .. Đối tượng được đặt tên với một dấu chấm đầu tiên, theo quy ước, "ẩn". Chúng không hiển thị trong ls hoặc trừ khi bạn chỉ định -a.

(Điều này có nghĩa rằng ... mục thư mục cho "tự" và "mẹ" được coi là ẩn.)

Để phù hợp với mục ẩn cũng có, sử dụng .*

Lệnh rm không loại bỏ các thư mục (khi không hoạt động đệ quy với -r). Hãy thử rm <directory> và xem. Ngay cả khi thư mục trống, nó sẽ từ chối.

Vì vậy, cách bạn loại bỏ tất cả (không giấu) các tập tin, đường ống, thiết bị, ổ cắm và liên kết tượng trưng từ một thư mục (nhưng để lại các thư mục con một mình) là trong thực tế:

rm /path/to/directory/* 

để cũng loại bỏ những người bị ẩn bắt đầu bằng .:

rm /path/to/directory/{*,.*} 

Cú pháp này là cú đúp mở rộng. Brace mở rộng không phù hợp với mô hình; nó chỉ là một cách ngắn gọn để tạo nhiều đối số, trong trường hợp này:

rm /path/to/directory/* /path/to/directory/.* 

lần mở rộng này diễn ra trước tiên và sau đó là hình cầu để tạo ra tên cần xóa.

Lưu ý rằng các giải pháp khác nhau được đăng ở đây có vấn đề khác nhau:

find /path/to/directory -type f -delete 

# -delete is not Unix standard; GNU find extension 
# without -maxdepth 1 this will recurse over all files 
# -maxdepth is also a GNU extension 
# -type f finds only files; so this neglects to delete symlinks, fifos, etc. 

Các GNU tìm ra giải pháp có lợi ích mà họ làm việc ngay cả khi số lượng các mục thư mục bị xóa là rất lớn: quá lớn để vượt qua trong một một cuộc gọi đến rm. Một lợi ích khác là việc xây dựng trong -delete không có vấn đề với đi qua tên đường dẫn buồn cười với một lệnh bên ngoài.

Cách giải quyết di động cho các vấn đề của quá nhiều mục thư mục là lập danh sách các mục với ls và ống để xargs:

(cd /path/to/directory ; ls -a | xargs rm --) 

Các dấu ngoặc đơn có nghĩa là "làm những lệnh trong một tiểu trình"; theo cách này ảnh hưởng của cd bị lãng quên, điều này rất hữu ích trong việc viết kịch bản. ls -a bao gồm các tệp ẩn.

Hiện tại, chúng tôi bao gồm -- sau rm có nghĩa là "đây là tùy chọn cuối cùng; mọi thứ khác là đối số không tùy chọn". Điều này bảo vệ chúng tôi chống lại các mục nhập thư mục có tên không thể phân biệt được từ các tùy chọn. Điều gì nếu một tập tin được gọi là -rf và kết thúc lập luận đầu tiên? Sau đó, bạn có rm -rf ... sẽ thổi tắt các thư mục con.

0

Simple vỏ globbing sẽ làm:

% tree 
. 
├── 1 
├── 2 
├── 3 
├── 4 
├── 5 
└── bar 
    ├── a 
    ├── b 
    ├── c 
    ├── d 
    └── e 

1 directory, 10 files 

% rm -f * 
rm: cannot remove ‘./bar’: Is a directory 

% tree . 
. 
└── bar 
    ├── a 
    ├── b 
    ├── c 
    ├── d 
    └── e 

1 directory, 5 files 

như trong Jens' câu trả lời, bạn có thể cần thêm một giây rm -f .* nhưng đây chỉ là nếu bạn mong đợi các file ẩn trong thư mục chính của bạn. Không cần kiểm tra loại (test -f) vì tùy chọn rm -f sẽ không xóa các thư mục. Tuy nhiên, điều này cũng sẽ xóa các tệp "đặc biệt" như liên kết tượng trưng và thiết bị chặn.

3

Tôi muốn biết liệu rm có thể xóa tất cả các tệp trong thư mục (nhưng không phải thư mục con hoặc tệp trong thư mục con) không?

Đó là dễ dàng:

$ rm folder/* 

Nếu không có sự -r, lệnh rm sẽ không chạm vào thư mục con hoặc các tập tin chúng chứa. Điều này sẽ chỉ xóa các tệp trong folder chứ không phải các thư mục con hoặc tệp của chúng.

Bạn sẽ thấy lỗi cho bạn biết rằng thư mục/foo là thư mục không thể xóa được, nhưng điều đó thực sự ổn với bạn. Nếu bạn muốn loại bỏ các thư này, chỉ cần chuyển hướng thiết bị lỗi chuẩn:

$ rm folder/* 2> /dev/null 

Bằng cách này, các trạng thái thoát của lệnh rm có thể không được bằng không, vì vậy bạn không thể kiểm tra rm lỗi. Nếu điều đó quan trọng, bạn sẽ phải lặp lại:

$ for file in * 
> do 
> [[ -f $file ]] && rm $file 
> [[ $? -ne 0 ]] && echo "Error in removing file '$file'" 
> done 

Điều này sẽ hoạt động trong BASH ngay cả khi tên tệp có không gian trong đó.

0

Cách đơn giản nhất để làm điều này là sử dụng:

rm * 

Để loại bỏ các thư mục, bạn phải xác định tùy chọn -r

rm -r 

để thư mục và bất cứ điều gì bạn chứa trong chúng sẽ không bị xóa bằng cách sử dụng

rm * 

trên trang người đàn ông cho rm, mục đích của nó là xóa tệp, đó là lý do tại sao công trình này hoạt động

Các vấn đề liên quan