Cách thoát khỏi trò chơi Không tìm thấy trận đấu nào


21

Khi sử dụng zsh, tôi nhận được thông báo "Không tìm thấy kết quả phù hợp" khi chọn một mẫu không phù hợp rmvà ngay cả khi chuyển hướng đầu ra.

# rm * > /dev/zero 2>&1
  zsh: no matches found: *

Làm thế nào tôi có thể thoát khỏi tin nhắn này?


Bạn đang cố gắng xóa mọi thứ trong thư mục hiện tại? Thư mục hiện tại là gì?
cutrightjm

Bạn có thể sử dụng setopt extended_glob(hoặc thậm chí đơn giản rm * >/dev/null 2>&1) nhưng thực sự bạn nên tạo ra một cách giải quyết để không cần rm *, điều đó hoàn toàn nguy hiểm
hóa học

Bạn nên thực sự chìm xuống /dev/nullsau đó dev/zero. Ngoài ra, chuyển hướng stderr của bạn đang thiếu một &; nó phải được 2>&1.
roaima

Thông báo lỗi được tạo bởi zshtrong quá trình đánh giá lệnh chứ không phải trong thời gian chạy của chính lệnh (do lỗi, lệnh thậm chí không chạy). Các chuyển hướng đầu ra ở đây sẽ chỉ ảnh hưởng đến đầu ra của lệnh chứ không ảnh hưởng đến chính trình bao.
Adaephon

Câu trả lời:


41

Hành vi này được kiểm soát bởi nomatchtùy chọn của Zsh . Theo mặc định, nếu một dòng lệnh chứa biểu thức toàn cầu không khớp với bất cứ thứ gì, Zsh sẽ in thông báo lỗi mà bạn nhìn thấy và hoàn toàn không chạy lệnh. Bạn có thể vô hiệu hóa điều này bằng cách chạy

setopt +o nomatch

Sau đó, các biểu thức toàn cầu không khớp với bất kỳ thứ gì sẽ được giữ nguyên và bạn sẽ nhận được thông báo lỗi từ rm(mà bạn có thể vô hiệu hóa bằng cách sử dụng -f, mặc dù đó là một ý tưởng tồi vì nó sẽ buộc loại bỏ trong các tình huống khác mà bạn không thể muốn).


4
Các hành vi cũng được kiểm soát bởi nullglobcshnullglobcác tùy chọn. Nếu nullglobđược đặt và không tìm thấy tệp phù hợp, mẫu sẽ bị xóa khỏi danh sách đối số thay vì tạo ra lỗi. Cài đặt cshnullglobcó hiệu ứng tương tự trừ khi tất cả các mẫu trong lệnh không khớp, trong trường hợp đó sẽ xảy ra lỗi. Lưu ý: cài đặt nullglobhoặc cshnullglobghi đè nomatch. Bạn cũng có thể đặt nullglobcho các mẫu đơn bằng cách sử dụng vòng loại toàn cầu N: rm *(N).
Adaephon

nomatchít hơn lý tưởng, đó là những gì vỏ giống như Bourne làm. Nếu mẫu không khớp, nó sẽ được chuyển thành rm(!) Khi đó rmsẽ báo lỗi hoặc tệ hơn là có thể xóa tệp sai cho một mẫu như *.[ch]ví dụ!
Stéphane Chazelas

9

Thay vào đó, bạn muốn nó làm gì? Không chạy rmchút nào (1)? Chạy nó với một *đối số theo nghĩa đen như trong các shell giống như Bourne khác (2)? Chạy nó không có đối số nào cả (3)?

  1. files=(*(N)); (($#files)) && rm -- $files. Hoặc (rm -- *) 2> /dev/nullnhưng điều đó cũng sẽ che giấu các lỗi chính hãng rmmà sẽ là ngớ ngẩn. Bạn có thể loại bỏ zshlỗi nhưng khôi phục stderr cho rmlệnh mặc dù với(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. Sau đó, giống như trong shđó zshbây giờ được mô phỏng cho dòng lệnh đơn lẻ đó, việc không khớp *được truyền theo nguyên trạng rmrmphàn nàn vì *tệp đó không tồn tại. Chúng ngăn chặn rm's stderr như bạn sẽ làm gì trong shđể ngăn chặn điều đó thông báo lỗi, nhưng một lần nữa, đó là ngớ ngẩn vì nó sẽ che giấu lỗi chính hãng bởi rmnhư trái ngược với các lỗi phát sinh do hành vi sai trái của shđi qua một nghĩa đen *đến rm. rm -f '*'sẽ không phàn nàn về một *tập tin chưa tồn tại , vì vậy bạn có thể làmemulate sh -c 'rm -f -- *'
  3. rm -- *(N). rmsẽ khiếu nại mặc dù khi không thông qua bất kỳ đối số, mặc dù một lần nữa, không rm -f: rm -f -- *(N).

Nói chung, rm -flà lệnh bạn muốn sử dụng nếu bạn muốn tất cả các tệp biến mất và chỉ gặp lỗi nếu không thể xóa các tệp hoặc IOW vẫn còn đó sau khi rmđã trả về. Bạn cũng thường muốn sử dụng -ftrong các tập lệnh để tránh người dùng bị nhắc nhở trong một số tình huống.

Ở đây, gọi rmkhi toàn cầu không khớp là sai. Các sh1 hành vi là sai. Nó vô hại đối với một kiểu như *, nhưng đối với một lượt thích *.[ch], việc chuyển qua trạng thái *.[ch]không khớp có thể khiến *.[ch]tệp bị xóa do nhầm lẫn:

$ ls
*.[ch]  foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch]  foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt

Không có một lỗi là điều hợp lý nhất để làm và là những gì zsh(và fish, csh, tcsh, bash -o failglobvà bản gốc Unix shell) does.

Và nếu bạn muốn tự chăm sóc cho trường hợp đặc biệt đó, hãy zshlàm cho nó dễ dàng với (N)vòng loại toàn cầu của nó (đối với noglob ) như trong trường hợp (1) ở trên. fish(ít nhất là trong phiên bản gần đây ) làm cho nó thậm chí còn dễ dàng hơn khi nó thực hiện một noglob ngầm cho setlệnh. Vì vậy, tương đương ở đó, sẽ là:

set files *
if count $files > /dev/null
  rm -f -- $files
end

Xem Tại sao nullglob không được mặc định để biết thêm chi tiết.


1 . Nói một cách chính xác, đó chỉ là shtừ vỏ Bourne (kể từ Unix V7 năm 1979); phiên bản trước của sh(mà đã gọi /etc/globtheo ký tự đại diện không thể viện chứng đó là nơi mà các glob tên xuất phát từ) đã hành xử giống như cshhoặc zsh -o cshnullglob, có nghĩa là /etc/globsẽ hủy bỏ lệnh nếu không có những đống có bất kỳ trận đấu (và sẽ ngăn chặn những đống không phù hợp nếu có ít nhất một trong số họ đã có bất kỳ trận đấu). Hành vi đã bị phá vỡ bởi vỏ Bourne.


Tôi nghĩ rằng anh ta hy vọng sẽ nhận được thông báo lỗi từ rmchứ không phải từ shell. Một cái gì đó như "rm: không thể xóa` * ': Không có tệp hoặc thư mục như vậy ".
Emmanuel

@Emmanuel, sau đó là 2: emulate sh -c 'rm -- *'để có được hành vi (lỗi IMO) của vỏ Bourne.
Stéphane Chazelas

@Stephane_Chazelas như đã viết, 2 là câu trả lời đúng cho câu hỏi mà anh không hỏi :).
Emmanuel

@Emmanuel, cả 3 trả lời câu hỏi: làm thế nào để thoát khỏi lỗi "Không khớp". Mã của OP ngăn chặn các rmlỗi. Đó là điều bạn sẽ làm trong các shell khác để khắc phục lỗi khi không có tệp phù hợp và điều đó cũng gây ra sự triệt tiêu các lỗi rm chính hãng. Câu trả lời của tôi phác thảo điều đó và hy vọng cho thấy hành vi của zsh là thích hợp hơn.
Stéphane Chazelas
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.