Как и все остальные сказали, переменная потребности $dnam
двойные кавычки. Вот почему:
[ ... ]
является псевдонимом команды test
. Если вы посмотрите в своей системе, вы увидите файл с именем /bin/[
или, возможно, /bin/usr/[
. В некоторых системах это жесткая ссылка на /bin/test
или /bin/usr/test
. Оператор if
выполняет, что происходит после if
, и если эта команда возвращает нулевой статус выхода, оператор if
выполнит пункт then
. В противном случае, если есть предложение else
, это будет выполнено вместо этого.
Чтобы обеспечить логическое тестирование, Unix включали команду test
, так что вы можете сделать это:
if test -d "$directory"
then
echo "Directory $directory exists!"
fi
Позже /bin/[
был добавлен как синтаксический сахар. Это идентично выше:
if [ -d "$directory" ]
then
echo "Directory $directory exists!"
fi
Теперь оба [
и test
являются встроенные команды, но они * до сих пор команды. Это означает, что оболочка интерполирует команду, а затем выполняет ее.
Попробуйте выполнить следующие действия:
$ set -xv # Turns on shell debugging
$ dnam="/home/bryan/renametest/C D"
dnam="/home/bryan/renametest/C D"
+ dnam='/home/bryan/renametest/C D'
$ test -d $dnam
test -d $dnam
+ test -d /home/bryan/renametest/C D
$ echo $?
echo $?
+ echo 1
1
$ test -d "$dnam" # Now with quotes
test -d $dnam
+ test -d "/home/bryan/renametest/C D"
$ echo $?
echo $?
+ echo 0
0
$ set +xv # Turn off the debuggin
Каждая команда повторила дважды. Первый раз, как написано, и второй раз после интерполяции строки. В рамках интерполяции оболочка разбивает параметры на пробел. Как вы можете видеть, команда test
проверяет наличие /home/bryan/renamtest/C
, который не существует и, следовательно, не доступен для записи. Я действительно удивлен, что команда test
не выдала сообщение об ошибке, потому что вы передали ему дополнительный параметр.
Во второй попытке вы добавили цитаты. Эти кавычки не позволяли оболочке разделять ваши параметры на пространстве и сохранять имя каталога как один параметр.
С [ ... ]
- это команда, вы должны учитывать интерполяцию переменных оболочки и другие проблемы. И, если вы не совсем осторожны, вы можете получить ошибки.
Хуже того, иногда может работать [ ... ]
, а иногда и нет. Если имя вашего каталога не содержит пробелов, оно будет работать должным образом. Представьте, что вы пишете программу, и вы ее проверяете, и все работает, потому что все профайлы, которые вы пробовали, не имеют пробелов. Затем кто-то использует вашу программу, но имеет место в каталоге. Значительное количество ошибок сценария оболочки выполняется для этого типа проблем в операциях if
.
Вот почему Баш представил тесты [[ ... ]]
. [[
- это не команда, а инструкция. Это означает, что оболочка не напрямую интерполирует результаты. Вместо этого параметры анализируются, а затем выполняется любая интерполяция. Таким образом, это работало бы:
dnam="/home/bryan/renametest/C D" # No "$" in front of the variable!
# Is the directory writable
if [[ ! -w $dnam ]] # No quotation marks needed!
then
# Not writable. Pop the error and exit.
echo "Directory $dnam is not writable"
err=1
fi
Это почти всегда лучше использовать тест [[ ... ]]
, а не тест [ ... ]
, чтобы идти вперед и войти в привычку.
еще одна незначительная ошибка, вы имели:
$dnam="/home/bryan/renametest/C D"
Это получает интерполированное оболочкой, так что переменная набор бытие независимо от значения $dnam
просто случается. Если $dnam
случилось с равным «Foo», вы бы делали это:
foo="/home/bryan/renametest/C D"
Не то, что вы хотите.
Вы хотите оставить $
, когда вы установите переменные:
dnam="/home/bryan/renametest/C D"
Я вижу две проблемы с вашим кодом, и не может воспроизвести ошибку, вы видите. Первая проблема ** $ dnam = **, которая не будет летать. Вторая проблема: вы должны предпочесть [[]] на []. В единственной версии я вижу ошибку «двоичного оператора». – tink
ой, извините ... строка $ dnam = была просто добавлена, чтобы я мог показать, что это было. Фактический код не имеет $. Это на самом деле: dnam = $ (dirname $ 1) \ " – user2021539
Изменение [] на [[]] приводит к [[: не найдено – user2021539