Как сделать так, чтобы 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

Дайте ссылку на документацию, пожалуйста. Не могли бы найти описание этой функции.
Георгий Советов


14

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

rm filethatdoesntexist 2> /dev/null 

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


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удалит этот файл.


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 вам новое сообщение get get error Проблема возникает, если ошибка генерируется не для STDERR 2, а для STDOUT 1 ... Это происходит, когда команда генерирует не ошибку, а предупреждение. Вам необходимо установить фильтр и удалить это сообщение. Но этот случай обычный.


1

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.