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

216491
Jason Baker

Я пишу 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. 

Это звучит почти как то, что я хочу, но я не совсем уверен в части разрешений. Есть ли способ сделать это?

277
Вы пробовали "rm" в песочнице? Похоже, `-f` делает именно то, что вы хотите, независимо от глобализации. JMD 14 лет назад 0
Если разрешения не позволят, rm с опцией `-f` все равно попытается удалить его. Это не удастся. Это не скажет вам, что это не удалось. Полезно, если имя файла является переменной или глобом. LawrenceC 11 лет назад 0

12 ответов на вопрос

234
Dave Webb

-fВариант, безусловно, то, что вы хотите использовать.

Подтверждение о разрешениях файла, на которые оно ссылается, таково:

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

Так rmчто предупредит вас, если вы попытаетесь удалить файл, на который у вас нет разрешения на запись. Это разрешено, если у вас есть права на запись в каталог, но это немного странно, поэтому rmобычно предупреждает вас об этом.

Большинство, но не все системы будут спрашивать (я думаю). Некоторые требуют `-i`. DaveParillo 14 лет назад 1
Если вы хотите получить сообщение об ошибке, но не код ошибки, см. Ответ [Giel Berkers] (http://superuser.com/a/887349/64750). Я использую `set -e` во всех моих скриптах bash, чтобы скрипт завершился после того, как любая команда выдаст ошибку. Я часто хочу, чтобы скрипт сообщал мне, выдал ли `rm` ошибку, но все равно продолжаю. продолжается. cledoux 7 лет назад 1
87
Giel Berkers

Another solution is this one: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Just add an OR-statement after your command:

rm -rf my/dir || true 

This way, when statement #1 fails (throws error), run statement #2, which is simply true.

Он печатает ошибку и продолжает выполнение, которое было желательным для моего случая. worldsayshi 8 лет назад 1
Или просто `rm -rf my / dir ||:`, чтобы быть еще более кратким (`:` - это сокращение от `true`) Godsmith 7 лет назад 4
Лучшее решение на мой взгляд. Легко увидеть, что происходит и почему код результата игнорируется. Мне это нравится! Mavamaarten 6 лет назад 0
72
Robert Li

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

-rm lexer.ml interpparse.ml interpparse.mli
Это все равно будет выводить ошибку на консоль, что научит вас игнорировать ошибки в выводе make, что, вероятно, не то, что вам нужно. rm -rf - лучший вариант на мой взгляд. Godsmith 7 лет назад 9
@ Godsmith Я бы лучше проигнорировал ошибку, чем принудительное рекурсивное удаление. Это может быть очень непослушным. И +1 для специфичного для makefile синтаксиса Daishi 6 лет назад 0
Если rm -rf может быть «непослушным», это означает, что вы используете make вне каталога под управлением версией. Зачем? Godsmith 6 лет назад 0
Дайте ссылку на документацию, пожалуйста. Не могли бы найти описание этой функции. George Sovetov 6 лет назад 0
@GeorgeSovetov https://www.gnu.org/software/make/manual/make.html#Errors Robert Li 6 лет назад 0
Я думаю, что это лучше. `-f` также пропускает интерактивный режим, пропускает файлы только для чтения и т. д. - однако это решение делает именно то, что запрашивал OP. Blauhirn 6 лет назад 0
9
user135299

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

rm filethatdoesntexist 2> /dev/null 

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

К сожалению, это все равно даст код ошибки. Shaun McDonald 10 лет назад 5
7
Nick Bastin

Если вы найдете способ обуздать имена файлов, rmне будете жаловаться, если не сможете найти совпадение. Так что что-то вроде lexer.m* interpparse.*и т. Д. Должно работать для вас (будьте осторожны, вы не слишком много удаляете, конечно). Кроме того, -fэто вполне разумный способ, если вы не надеетесь, что права доступа к файлам избавят вас от удаления файла, который вы не хотели - если вы не хотите его удалять, не помещайте его в списке.

Об этом не может быть и речи, поскольку есть файл lexer.mll, который я не хочу удалять. Спасибо за показ, почему -f разумно. Я предполагаю, что я склонен быть чрезмерно осторожным после слишком многих ошибочных `sudo rm -rf`. Jason Baker 14 лет назад 0
Даже не более строгий `lexer.m?` ...? Это поймало бы `lexer.ml` и` lexer.mz`, но не `lexer.mll` или` lexer.mla`. JMD 14 лет назад 0
@JMD: Я полагаю, что это зависит от вашей оболочки и от того, какую поддержку сопоставления с образцом она предлагает для глобализации. Nick Bastin 14 лет назад 1
5
mouviciel

Опция -f означает, что вам не будет предложено, если что-то не так, как ожидалось. Это не значит, что разрешения не учитываются.

Если у вас недостаточно прав для удаления файла, он не будет удален.

НО, если у вас достаточно привилегий для изменения привилегий, ваш файл будет удален. Это тот случай, когда вы являетесь владельцем файла с правами только для чтения для владельца (-r --------). Как владелец, вы можете chmod u+w, а затем удалить его: rm -fудалит этот файл.

3
Bogdan

Может быть, может помочь строка, аналогичная с:

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

Я знаю, что это не очень умно, но это делает работу.

2
reinierpost

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

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

Жаль, что Makefiles не может совместно использовать определения функций оболочки между строками.

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

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

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

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

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

Похожие вопросы