Как сделать так, чтобы rm не выдавал ошибку, если файл не существует?

324

Я пишу make-файл, который очистит некоторые ненужные файлы в конце компиляции. Если цель уже была создана, она, конечно, пропустит эту цель, и бесполезный файл может не оказаться там. Так что, если я сделаю это:

rm lexer.ml interpparse.ml interpparse.mli

Я могу получить ошибки, потому что один из файлов не существует. Есть ли способ сказать, rmчтобы игнорировать эти файлы?

Читая справочную страницу, я вижу следующую опцию:

 -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опцией все равно попытается удалить его. Это не удастся. Это не скажет вам, что это не удалось. Полезно, если имя файла является переменной или глобом.
LawrenceC
просто для полноты: есть то, rm --interactive=neverчто действует как rm -fза исключением того, что оно возвращает состояние выхода из ошибки. подробности смотрите здесь: unix.stackexchange.com/questions/72864/…
lesmana

Ответы:

279

-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
120

Вот еще одно решение: 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
Лучшее решение на мой взгляд. Легко увидеть, что происходит и почему код результата игнорируется. Мне это нравится!
Mavamaarten
76

Я опаздываю на вечеринку, но я использую это все время. В make-файле добавьте -в начало строки, чтобы игнорировать возвращаемое значение этой строки. Вот так:

-rm lexer.ml interpparse.ml interpparse.mli
Роберт Ли
источник
9
Это все равно будет выводить ошибку на консоль, что научит вас игнорировать ошибки в выводе make, что, вероятно, не то, что вам нужно. rm -rf - лучший вариант на мой взгляд.
Кузнец
@ Godsmith Я бы лучше проигнорировал ошибку, чем принудительное рекурсивное удаление. Это может быть очень непослушным. И +1 для специфичного для makefile синтаксиса
Daishi
Если rm -rf может быть «непослушным», это означает, что вы используете make вне каталога под управлением версией. Почему?
Godsmith
Дайте ссылку на документацию, пожалуйста. Не могли бы найти описание этой функции.
Георгий Советов
@GeorgeSovetov gnu.org/software/make/manual/make.html#Errors
Роберт Ли
14

Если вы не хотите использовать опцию -f, альтернативой является:

rm filethatdoesntexist 2> /dev/null 

Это только предотвратит печать ошибок.

user135299
источник
8
К сожалению, это все равно даст код ошибки.
Шон Макдональд
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удалит этот файл.

mouviciel
источник
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 не может совместно использовать определения функций оболочки между строками.

reinierpost
источник
Вы пытались использовать \ (обратную косую черту) в конце строки, чтобы она продолжалась в следующем?
около
@ Some: Да, они могут быть распределены по нескольким строкам, но чтобы разделить их по рецептам, вы должны поместить определение в переменную make.
reinierpost
3

Вот что я использую в сценариях оболочки. Он скрывает сообщение об ошибке и код ошибки.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
источник
как насчетrm doesnotexist 2&> /dev/null
user8162
1

Вы можете коснуться файлов, прежде чем вы их. что бы создать их, если они не существуют :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
commonpike
источник
1

написать rm -rf ppp>/dev/null 2>&1 вам новое сообщение get get error Проблема возникает, если ошибка генерируется не для STDERR 2, а для STDOUT 1 ... Это происходит, когда команда генерирует не ошибку, а предупреждение. Вам необходимо установить фильтр и удалить это сообщение. Но этот случай обычный.

Анатолий
источник
1

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

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

добавьте больше тестовых предложений, если есть еще файлы, которые вы хотите быть уверенными в существовании.


источник