Як позбутися "Не знайдено відповідності" під час запуску "rm *"


22

Використовуючи zsh, я отримую повідомлення "Не знайдено відповідності", коли вибираю шаблон, який не підходить rmі який навіть перенаправляє вихід.

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

Як я можу позбутися цього повідомлення?


Ви намагаєтесь видалити все з поточного каталогу? Який поточний каталог?
cutrightjm

Ви можете використовувати setopt extended_glob(або навіть просто rm * >/dev/null 2>&1), але насправді вам слід вирішити, щоб цього не потрібно rm *, це прямо небезпечно
грохмал

/dev/nullТоді вам слід справді зануритися dev/zero. Також у вашому stderr переспрямуванні відсутнє &; так і має бути 2>&1.
roaima

Повідомлення про помилку генерується під zshчас оцінки команди, а не під час виконання самої команди (через помилку команда навіть не виконується). Перенаправлення виводу тут впливатиме тільки на вихід команди, а не на саму оболонку.
Adaephon

Відповіді:


42

Така поведінка контролюється nomatchваріантом Zsh . За замовчуванням, якщо командний рядок містить вираз глобусу, який нічого не відповідає, Zsh надрукує повідомлення про помилку, яке ви бачите, і не виконає команду взагалі. Ви можете відключити це, запустивши

setopt +o nomatch

Тоді глобусні вирази, які нічого не відповідають, залишаться як є, і ви отримаєте повідомлення про помилку rm(яке ви можете відключити -f, хоча це погана ідея, оскільки це змусить видалити в інших ситуаціях, коли ви можете не хочу).


4
Поведінка також контролюється nullglobі cshnullglobваріантами. Якщо nullglobвстановлено і не знайдено відповідний файл, шаблон вилучається зі списку аргументів замість генераціїg помилки. Налаштування cshnullglobмає подібний ефект, якщо всі шаблони команди не відповідають, і в цьому випадку буде повідомлено про помилку. Примітка: налаштування nullglobабо cshnullglobпереосмислення nomatch. Можна також встановити nullglobдля окремих моделей за допомогою Глоб специфікатор N: rm *(N).
Adaephon

nomatchменш ідеально, саме так роблять раковини, схожі на Борна. Якщо шаблон не збігається, він передається як-є rm(!), Після чого rmвидасть помилку, або, що ще гірше, може видалити неправильний файл для шаблону, наприклад, *.[ch]наприклад!
Стефан Шазелас

9

Що б ви хотіли це зробити замість цього? Не бігали rmвзагалі (1)? Виконати це з буквальним *аргументом, як в інших оболонках Борна (2)? Запустити його без аргументів (3)?

  1. files=(*(N)); (($#files)) && rm -- $files. Або (rm -- *) 2> /dev/nullале це також приховувало б справжні помилки, через rmякі було б нерозумно. Ви можете відкинути zshпомилку, але відновити stderr для rmкоманди, хоча з(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null. Тоді, як, в shякому zshзараз емульовано для цього єдиного командного рядка, невідповідний *передається як є rmі rmскаржиться на те, що цього *файлу не існує. Ми пригнічуємо rmstderr, як ви робили, shщоб придушити це повідомлення про помилку, але, знову ж таки, це нерозумно, як це приховувало б справжні помилки, на rmвідміну від помилки, що трапилася внаслідок неправильної поведінки при shпередачі літералу *на rm. rm -f '*'не поскаржився б на неіснуючий *файл, тож ви можете це зробитиemulate sh -c 'rm -f -- *'
  3. rm -- *(N). rmбуде скаржитися , хоча , коли він не пропустив жодного одного аргументу, хоча знову ж , чи не rm -f: rm -f -- *(N).

Як правило, rm -fце команда, яку ви хочете використовувати, якщо ви хочете, щоб усі файли пішли і отримали помилку лише в тому випадку, якщо файли не вдалося видалити або IOW все ще є після rmповернення. Ви також хочете використовувати -fв сценаріях, щоб уникнути того, що користувач буде запропонований в деяких ситуаціях.

Тут дзвонити, rmколи глобус не відповідає, неправильно. sh1 поведінка є неправильним. Це нешкідливо для такого типу візерунка *, але для такого типу *.[ch], передача *.[ch]як є, коли вона не відповідає, може призвести *.[ch]до помилкового видалення файлу:

$ 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

В іншому випадку з помилкою найрозумніше , що потрібно зробити , і це те , що zshfish, csh, tcsh, bash -o failglobі оригінальний Unix оболонки) робить.

А якщо ви хочете подбати про той особливий випадок, zshце полегшує роботу з його (N)глобальним класифікатором (для ноглобу ), як у випадку (1) вище. fish(принаймні, в останній версії ) це робить ще простіше, оскільки це робить неявний ноглоб для setкоманди. Отже, еквівалент там буде:

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

Дивіться, чому nullglob не використовується за замовчуванням для отримання детальної інформації.


1 . Власне кажучи, це лише shз оболонки Bourne (починаючи з Unix V7 в 1979 році); більш ранні версії sh(які закликали /etc/globкотирувати подстановочні символи, звідки походить ім'я глобуса ) поводилися так, cshабо zsh -o cshnullglob, тобто, /etc/globскасували б команду, якщо жоден із глобусів не мав відповідності (і придушував би невідповідні глобуси, як мінімум одна з них мала будь-яку відповідність). Поведінка була порушена оболонкою Борна.


Я думаю, він розраховує отримати повідомлення про помилку, rmа не від оболонки. Щось на кшталт "rm: не можна видалити` * ': такого файлу чи каталогу немає ".
Еммануїл

@Emmanuel, тоді це 2: emulate sh -c 'rm -- *'отримати поведінку (баггі IMO) поведінки оболонки Борна.
Стефан Шазелас

@Stephane_Chazelas, як написано, 2 - це правильна відповідь на питання, яке він не задавав :).
Еммануїл

@Emmanuel, усі 3 відповідають на питання: як позбутися помилки "Не відповідає". Код ОП пригнічує rmпомилки. Це те, що ви зробили б в інших оболонках, щоб придушити помилку, коли немає відповідного файлу, і це також спричиняє придушення справжніх RM-помилок. Моя відповідь окреслює це, і, сподіваюся, показує, наскільки краще поведінка zsh.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.