Як змусити 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.