281

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


Я пишу 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 делает именно то, что вы хотите, независимо от глобализации. (27 ноября 2009 г. в 17:02)

Если разрешения не позволят, rm с опцией -f все равно попытается удалить его. Это не удастся. Это не скажет вам, что это не удалось. Полезно, если имя файла является переменной или глобом. (13 июня '12 в 1:24)

Ответов: 12

236

Опция -f определенно то, что вы хотите использовать.

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

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

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

Большинство, но не все системы будут спрашивать (я думаю). Некоторые требуют -i . (27 ноября 2009 г. в 18:11)

Если вы хотите получить сообщение об ошибке, но не код ошибки, см. Ответ Гиль Беркерс . Я использую set -e во всех моих скриптах bash, чтобы скрипт завершился после того, как любая команда выдаст ошибку. Я часто хочу, чтобы скрипт сообщал мне, если rm выдал ошибку, но все равно продолжаю. продолжается. (6 июня '16 в 4:05)
92

Вот еще одно решение: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Просто добавьте оператор OR после вашей команды:

rm -rf my/dir || true

Таким образом, когда оператор № 1 не выполняется (выдает ошибку), запустите оператор № 2, что просто true .

Он печатает ошибку и продолжает выполнение, которое было желательным для моего случая. (29 февраля '16 в 14:28)

Или просто rm -rf my/dir ||: , чтобы быть еще более кратким (: - это сокращение от true ) (октябрь 4 '16 в 14:55)

Лучшее решение на мой взгляд. Легко увидеть, что происходит и почему код результата игнорируется. Мне это нравится! (3 октября '17 в 14:13)
73

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

  -rm lexer.ml interpparse.ml interpparse.mli 

Это все равно будет выводить ошибку на консоль, что научит вас игнорировать ошибки в выводе make, что, вероятно, не то, что вам нужно. rm -rf - лучший вариант на мой взгляд. (4 октября '16 в 14:54)

@ Godsmith Я бы лучше проигнорировал ошибку, чем принудительное рекурсивное удаление. Это может быть очень непослушным. И +1 для специфичного для make-файла синтаксиса (6 декабря 17 в 15:06)

Если rm -rf может быть «непослушным», это означает, что вы используете make вне каталога под управлением версией. Зачем? (8 декабря 17 в 7:27)

Дайте ссылку на документацию, пожалуйста. Не могли бы найти описание этой функции. (30 января '18 в 16:50)

Я думаю, что это лучше. -f также пропускает интерактивный режим, пропускает файлы только для чтения и т. д. - однако это решение делает именно то, что запрашивал OP. (17 марта '18 в 6:39)
10

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

rm filethatdoesntexist 2> /dev/null 

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

К сожалению, это все равно даст код ошибки. (20 ноября '13 в 17:37)
7

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

Об этом не может быть и речи, поскольку есть файл lexer.mll, который я не хочу удалять. Спасибо за показ, почему -f разумно. Я предполагаю, что я склонен быть слишком осторожным после того, как слишком много введенных в заблуждение sudo rm -rf . (27 ноября 2009 г. в 16:53)

Даже более строгого lexer.m? ...? Это будет перехватывать lexer.ml и lexer.mz , но не lexer.mll или lexer.mla . (27 ноября 2009 г. в 16:58)

@JMD: Я полагаю, что это зависит от вашей оболочки и от того, какую поддержку сопоставления с образцом она предлагает для глобализации. (29 ноября 2009 г. в 0:56)
5

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

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

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

3

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

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

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

2

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

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

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

Вы пытались использовать \ (обратную косую черту) в конце строки, чтобы она продолжалась в следующем? (31 июля '12 в 19:35)

@ Some: Да, они могут быть распределены по нескольким строкам, но чтобы разделить их по рецептам, вы должны поместить определение в переменную make. (1 октября '12 в 13:56)
2

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

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

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

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

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

0

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

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

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

Дополнить ответ