Я писал некоторые сценарии и написал что-то вроде
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Случилось так, что по глупости я выполнил вторую строку, не выполняя первую. Оказалось, что [-d ""] возвращает true, и выражение стало
rm -rf /*
К счастью, это была только тестовая машина, и я не был sudo, но хотя я потерял некоторые данные
Мой вопрос, почему [-d ""] возвращает true ?? документация ясно заявляет, что проверяет, существует ли путь и является ли папка
Я решил проблему с помощью
[ -e $ARTIFACTS ]
который, кажется, работает
ура
rm -rf $ARTIFACTS
без/*
. Это также удалит$ARTIFACTS
каталог, и это нормально, потому что если я хочу быть уверенным, что он существует, прежде чем что-то в него помещать, я всеmkdir -p $ARTIFACTS
равно выполню. Он также удалит скрытые файлы внутри$ARTIFACTS
, что тоже хорошо, потому что я бы не стал писать,rm -rf $ARTIFACTS/*
если бы$ARTIFACTS
содержал что-то, что хотел сохранить.Ответы:
1. Эти два теста возвращают true :
в соответствии с POSIX (как объяснено @Tim).
2. Но это возвращает ложь ( не верно, как указано в вопросе)
потому что
test
вызывается с двумя аргументами (хотя второй является пустой строкой).3. Поэтому лучше использовать
[[ … ]]
вместоtest
([ … ]
), который предоставляет большинство (все?) Текущих оболочек. Эта конструкция проверяет, достаточно ли вы указали аргументов (в противном случае выдает ошибку и прерывает работу).или просто ведет себя так, как и следовало ожидать:
4. И, как отмечает @Gilles, еще важнее сделать двойные кавычки. Таким образом,
-d "$SOME_UNSET_VAR"
расширяется до-d ""
и возвращает false даже сtest
(равен случаю 2). Следовательно, это также совместимо с оболочкой Bournesh
:протестировано с bash 3.00.16 (1) и 4.1.5 (1)
источник
[[ … ]]
но не простыеsh
. Действительно важная практика , чтобы поместить в двойные кавычки подстановки команд :[ -d "$ARTIFACTS" ]
.На этот вопрос уже ответили на StackOverflow. Он говорит, что в соответствии со стандартом POSIX,
test
всегда должен возвращать успешный, если он вызывается с точно одним непустым аргументом (и без других аргументов).Это также должно быть в случае
test -e
(и на самом деле это в моей системе), поэтому будьте осторожны.Вместо этого используйте:
test
будет вызван с двумя аргументами, даже если переменная пуста и в этом случае вернет false.источник
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
не лучше: он обслуживает только тот конкретный случай, когда$ARTIFACTS
он пуст, но не работает, когда$ARTIFACTS
может содержать пробелы или\[?*
.[ -d "$ARTIFACTS" ]
это правильный способ сделать это (или[[ -d $ARTIFACTS ]]
в оболочках, которые имеют[[ … ]]
).Вы не правы . Это работает, потому что
$ARTIFACTS
теперь настроено на что-то.Когда переменная не установлена, то говоря
или
бы как оценить,
true
так как это означает , говоряа также
соответственно. (Говоря
[ foobar ]
всегда будет оценивать как истину.)поговорка
пригодится в таких ситуациях.
help set
скажу вам:источник
Убедитесь, что вы установили переменную ARTIFACTS и проверяли ARTIFCATS. Возможно опечатка?
В любом случае, -d так же, как и -e, дадут одинаковые результаты для неустановленных переменных.
Поэтому используйте двойные кавычки, и это поможет вам.
ПРИМЕЧАНИЕ. Если в вашей папке «/ SOME / PATH» есть пробел, упомянутый вами скрипт сломается с ошибкой «ожидается двоичный оператор».
Пример:
все будет хорошо. Не забудьте также поставить кавычки в
rm
вызове (rm -rf $ARTIFACTS
с удовольствием удалите, а/home
потом пожалуетесь на то, чтоbackup/*
не существует).Кроме того, включение
-L
проверки позволит убедиться, что это каталог, а не просто символическая ссылка на каталог.Итак, в основном,
источник