Почему [ -d $dirname ] совпадает, когда переменная пуста или не установлена, и почему это приводит к удалению содержимого домашнего каталога?

Как обсуждалось выше :проблема синхронизации; ввести сон между запуском терминального сервера и открытием нового терминала.:)

4
27.06.2020, 22:12
2 ответа

Когда cdне передан аргумент, он изменится на каталог по умолчанию (, в большинстве случаев домашний каталог пользователя,$HOME).

Интересная часть этого вопроса заключается в том, что когда вы ничего не передаете -dоператору bash testили [, встроенному -, bash, по моему мнению, завершает работу с 0 (, это неожиданно ).

Когда вы устанавливаете dirnameпустую переменную, вы, по сути, запускаете это:

if [ -d ]; then
    cd && rm *
fi

Меня удивляет, что код внутри этого блока ifвыполняется, но я могу подтвердить это на своей машине. Как поясняется в комментарии выше, testбольше не интерпретирует -dкак оператор и просто возвращает 0, потому что это ненулевая строка -. Один из способов защититься от такого поведения — убедиться, что вы цитируете свои переменные :

.
if [ -d "$dirname" ]; then
    cd "$dirname" && rm *
fi

В этом случае, если $dirnameпусто, вы будете передавать ""оператору -d, который правильно оценивает ненулевой код выхода, отличный от -, поэтому код внутри блока не выполняется.

12
18.03.2021, 23:23

Незакавыченное $dirnameподлежит разбиению на слова, и если оно пустое, оно удаляется как в [ -d $dirname ], так и в cd $dirname, оставляя только [ -d ]и cd.

В первом случае [видит только один аргумент (между [и ]), и в этом случае проверка состоит в том, чтобы увидеть, является ли этот аргумент не -пустой строкой. -dесть, значит тест верен. (Это похоже на то, как [ -z $var ]проверяет, пусто ли $var, но [ -n $var ]вообще не работает.)

Что касается cd, обычный cdизменится на домашний каталог пользователя, так что здесь происходит rm *.


При использовании [[.. ]]разбиения слов не происходит, поскольку [[— это специальная конструкция оболочки, в отличие от [, которая является обычной командой.

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

if [ -d "$dirname" ]; then
    cd -- "$dirname" && rm./*
fi

См.:

12
18.03.2021, 23:23

Теги

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