Як змусити rm не помилитися, якщо файл не існує?


329

Я пишу makefile, який очистить кілька непотрібних файлів наприкінці компіляції. Якщо мета вже досягнута, вона, звичайно, пропустить цю ціль, і марний файл може не бути там. Тож якщо я це роблю:

rm lexer.ml interpparse.ml interpparse.mli

Я можу отримати помилки, оскільки один з файлів не існує. Чи є якийсь спосіб сказати rmігнорувати ці файли?

Читаючи сторінку man, я бачу такий варіант:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

Це звучить як майже те, що я хочу, але я не дуже впевнений у частині дозволів. Чи є спосіб це зробити?


Ви спробували дещо rmв пісочниці? Схоже, -fробиться саме те, що ти хочеш, незалежно від глобалізації.
JMD

Якщо дозволи не дозволять, rm з -fможливістю все-таки спробує її видалити. Це не вдасться. Це не скаже вам, що не вдалося. Корисно, якщо ім'я файлу є змінною або глобусом.
ЛоуренсC

тільки для повноти: є те, rm --interactive=neverщо діє як, rm -fкрім цього він повертає статус виходу з помилки. дивіться тут для більш детальної інформації: unix.stackexchange.com/questions/72864/…
lesmana

Відповіді:


282

-fВаріант, безумовно , то , що ви хочете використовувати.

Підтвердженням дозволів на файли, на які він посилається, є таким:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

Тож rmпопереджатиме вас, якщо ви спробуєте видалити файл, на який у вас немає дозволу на запис. Це дозволено, якщо у вас є дозволи на запис у каталозі, але це трохи дивно, тому rmзазвичай вас попереджає про це.


1
Більшість, але не всі системи запитують (я думаю). Деякі вимагають -i.
DaveParillo

1
Якщо ви хочете повідомлення про помилку, але не код виходу з помилки, дивіться відповідь Giel Berkers . Я використовую set -eу всіх своїх скриптах bash, щоб скрипт вийшов після того, як будь-яка команда видає помилку. Я часто хочу, щоб сценарій повідомив мені, чи rmпомилився, але продовжуйте все одно. продовжується.
cledoux

124

Ще одне рішення це: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Просто додайте оператор OR АБС після команди:

rm -rf my/dir || true

Таким чином, коли оператор №1 виходить з ладу (кидає помилку), запустіть оператор №2, що просто true.


4
Він друкує помилку і продовжує виконання, яке було бажане для мого випадку.
worldsayshi

9
Або просто rm -rf my/dir ||:бути ще більш лаконічним ( :скорочується true)
Godsmith

Краще рішення на мій погляд. Це легко видно, що відбувається і чому код результату ігнорується. Мені це подобається!
Мавамаартен

76

Я запізнююсь на вечірку, але цим користуюся весь час. У makefile додайте -до початку рядка, щоб ігнорувати повернене значення цього рядка. Приблизно так:

-rm lexer.ml interpparse.ml interpparse.mli

9
Це все ще буде друкувати помилку на консолі, яка навчає вас ігнорувати помилки у виведенні make, що, мабуть, не те, що ви хочете. rm -rf - на мій погляд, кращий варіант.
Godsmith

@Godsmith Я б швидше ігнорував помилку, ніж змушував рекурсивне видалення. Це може бути дуже неслухняно. І +1 для конкретного синтаксису makefile
Daishi

Якщо rm -rf може бути "неслухняним", це означає, що ви використовуєте make поза каталогом під контролем версій. Чому?
Godsmith

Дайте посилання на документацію, будь ласка. Не вдалося знайти опис цієї функції.
Георгій Совєтов


14

Якщо ви не хочете використовувати опцію -f, альтернативою є:

rm filethatdoesntexist 2> /dev/null 

Це просто запобіжить друку помилок.


9
На жаль, це все одно надасть код виходу з помилки.
Шон Макдональд

8

Якщо ви знайдете спосіб глобалізувати імена файлів, rmне поскаржтесь, якщо він не може знайти збіг. Отже, щось на зразок lexer.m* interpparse.*тощо повинно працювати для вас (будьте обережні, звичайно, що ви не видаляєте занадто багато). Крім того, -fце цілком розумний спосіб, якщо ви не сподіваєтесь, що дозволи на збереження файлів позбавлять вас від видалення файлу, який ви не хотіли - якщо ви не хочете його видалити, не ставте його у списку.


Глобус не підлягає сумніву, оскільки є файл lexer.mll, який я не хочу видаляти. Дякуємо, що показали, чому -f розумно. Я гадаю, що я схильний бути надто обережним після занадто великої кількості помилок sudo rm -rf.
Джейсон Бейкер

Навіть не більш обмежувальний lexer.m?...? Це спіймало б lexer.mlі lexer.mz, але ні lexer.mllабо lexer.mla.
JMD

1
@JMD: Я гадаю, це залежить від вашої оболонки та підтримки, яка відповідає образам, яку вона пропонує для глобалізації.
Нік Бастін

6

Опція -f означає, що вам не підкажуть, якщо щось не буде таким, як очікувалося. Це не означає, що дозволи не враховуються.

Якщо у вас недостатньо привілеїв для видалення файлу, він не буде видалений.

Але , якщо у вас є достатньо привілеїв для зміни привілеїв, файл буде видалено. Це той випадок, коли ви є власником файлу з дозволами для читання лише для власника (-r --------). Як власник, ви можете chmod u+w, а потім видалити: rm -fвидалить цей файл.


5

Можливо, може допомогти рядок, подібний до:

touch fakefile.exe fakefile.o && rm *.o *.exe

Я знаю, що це не дуже розумно, але це робить свою роботу.


3

Альтернатива:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Дуже погано Makefiles не може ділитися визначеннями оболонки в рядках.


Ви намагалися використовувати \ (зворотну косу рису) в кінці ряду, щоб продовжувати її продовжувати?
десь

@some: Так, вони можуть бути розповсюджені в декілька рядків, але для того, щоб поділити їх у різних рецептах, ви повинні поставити визначення у змінну make.
reinierpost

3

Ось що я використовую в скриптах оболонки. Він приховує повідомлення про помилку та код помилки.

rm doesnotexist 2> /dev/null || echo > /dev/null

як щодоrm doesnotexist 2&> /dev/null
user8162

1

ви можете торкнутися файлів, перш ніж їх виправити. це створило б їх, якщо їх не існує :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli

1

написати rm -rf ppp>/dev/null 2>&1 вам новіше отримати повідомлення про помилку Проблема виникає, якщо помилка генерує не STDERR 2, а STDOUT 1 ... Це відбувається, коли команда генерує не помилку, а попередження. Потрібно встановити фільтр і видалити це повідомлення. Але цей випадок звичайний.


1

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

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

додайте більше тестових пропозицій, якщо є більше файлів, для яких ви хочете бути впевнені.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.