Выполнение команды в выражении `if` и при успешном выполнении последующих действий

Я пытался выполнить программу, которая создаст каталог на основе полного пути, предоставленного ему из приглашения, и, если каталог уже существует, он вернет ошибку (для «каталог уже существует») и снова запросит имя в рекурсивной функции.

Вот что я пробовал: скажем, файл, test1 в нем:

 #!/bin/bash echo "enter the directory name" read ab check(){ if (( echo `mkdir $ab` 2>/dev/null )); then echo "directory created " echo `ls -ld $ab` exit else echo "try again " echo "enter new value for directory:" read ab check fi } check 

Проблема здесь в том, что каталог существует, тогда программа работает нормально, но если она не существует, она создает ее, а затем переходит к другой части программы.

Эхо всегда преуспевает. Без него и подоболочки:

 #!/bin/bash echo "enter the directory name" read ab check(){ if mkdir "$ab" 2>/dev/null; then echo "directory created " ls -ld "$ab" exit else echo "try again " echo "enter new value for directory: " read ab check fi } check 
 (( echo `mkdir $ab` 2>/dev/null )) bash: ((: echo 2>/dev/null : syntax error in expression (error token is "2>/dev/null ") 

Двумерные круглые скобки окружают арифметические выражения . Эта команда не делает ничего близкого к тому, что вы намеревались. mkdir $ab ничего не пишет для стандартного вывода, поэтому `mkdir $ab` – пустая строка, поэтому содержание арифметического выражения равно echo 2>/dev/null . Знак > – это оператор «больше», а echo – имя переменной. Арифметическое выражение синтаксически неверно (вы не можете иметь переменную, за которой следует буквальное целое число). Поскольку команда синтаксически некорректна, она возвращает статус ошибки, а ветвь else берется.

Чтобы проверить статус возврата команды, просто напишите эту команду.

 if mkdir -- "$ab" 2>/dev/null 

Дополнительные советы:

  • Плохая идея скрыть ошибки из команды. Пользователь должен знать, разрешена ли ошибка, ошибка ввода-вывода и т. Д. Чтобы создать каталог, если он не существует и не удается, если каталог уже существует, используйте mkdir -p -- "$ab" .
  • Всегда используйте двойные кавычки вокруг переменных замещений .
  • Если значение ab начинается с тире, оно будет интерпретироваться как опция. Поместите -- сначала пометить конец опций.
 tries=0 while [ "$((tries+=1))" -le 5 ] || ! break printf 'enter dirname: > ' IFS= read -r dir && if ! mkdir -- "$dir" then echo try again else ! echo Success\! fi do :; done 

Я не уверен, почему вы хотите скрыть статус выхода таким образом, но я думаю, что вышеприведенное должно получить что-то вроде инверсии, которую вы ищете, – и он должен выйти после ограниченного количества $tries .

Если я запустил его …?

 enter dirname: > . mkdir: cannot create directory '.': File exists try again enter dirname: > . mkdir: cannot create directory '.': File exists try again enter dirname: > . mkdir: cannot create directory '.': File exists try again enter dirname: > . mkdir: cannot create directory '.': File exists try again enter dirname: > . mkdir: cannot create directory '.': File exists try again 

И опять…

 enter dirname: > doesntexist Success! 

Эта идея сделает вещи немного более сложными, но я предлагаю, чтобы более правильный способ сделать это – использовать правильные тесты в вашем скрипте. Что-то вроде:

 #!/bin/bash if [[ -n $1 ]]; then dirname=$1 fi if [[ -z $dirname ]]; then echo "Enter directory name." read dirname fi check() { if [[ -d "$dirname" ]]; then echo "Directory already exists." echo "Enter new directory name." read dirname check elif [[ -e "$dirname" ]]; then echo "$dirname already exists, but is not a directory." echo "Enter new directory name." read dirname check else if mkdir -p -- "$dirname"; then echo "Directory created" ls -ld "$dirname" fi exit fi } check 

Это позволит сохранить сообщение об ошибках из вызываемого вами вызова (mkdir), а также выполнить некоторые полезные тесты, чтобы дать отзыв о том, почему попытка не удалась. Кроме того, вы можете опционально передать нужное имя каталога в качестве аргумента командной строки, и он попросит вас ввести его во вторую попытку.