На этот вопрос уже есть ответ здесь:
Я пытаюсь написать bash, чтобы запросить у пользователя имя файла, и, если файл существует, разрешить им перезаписать или добавить файл. По какой-то причине я продолжаю возвращаться с синтаксической ошибкой, несмотря на наличие проблемы. К сожалению, я не так хорошо знаком с Bash, как с Python, и путаю их синтаксис. Тем не менее, см. Ниже:
#!/bin/bash
echo "Please enter the name of your destination file: "
read destFile
if [ -f "$destFile" ]; then
echo "This file exists."
fi
echo "Please enter the name of your source file: "
read sourceFile
echo "Do you want to 1) Overwrite, 2) Append, 3) Exit?"
echo "Please select your option: "
options=("Overwrite" "Append" "Exit")
while [ -e "$sourceFile" ]; do
select opt in "${options[@]}"; do
case "$opt" in
"Overwrite")
cp "$sourceFile" "$destFile"
echo "Copy Completed."
;;
"Append" )
cat "$sourceFile" >> "$destFile"
echo "Append Completed."
;;
"Exit" )
echo "Script Terminated"
break
;;
esac
break
done
done
Поскольку Вы заявили это, проблема, которую Вы пытаетесь решить, (добавленный акцент):
Я пытаюсь записать сценарий удара для запроса пользователя имя файла, и если файл существует, позвольте им перезаписывать или добавлять файл.
Любопытно, код в Вашем сценарии, который проверяет, существует ли файл, не использует if
, хотя это, вероятно, должно. Вместо этого это использует while
:
while [ -e "$sourceFile" ]; do
Это - цикл. Если исходный файл существует, все в том цикле, до соответствия
done
на последней строке Ваших выполнений сценария. Это - a while
цикл, поэтому после того, как это запустит в первый раз тест, выполняется снова. Если файл все еще существует, тело цикла работает снова, и так далее, и так далее, и так далее.
Но ничто в теле цикла никогда не заставляет файл останавливаться существующий. Эти четыре возможности:
Пользователь вводит a 1
и исходный файл копируется по целевому файлу. Это скопировано, не перемещено, таким образом, исходный файл все еще существует с тем же именем.
Пользователь вводит a 2
и содержание исходного файла добавляется в целевой файл. Однако исходный файл не удален; это все еще там.
Пользователь вводит a 3
и a Script Terminated
сообщение печатается. Это сразу сопровождается a break
команда. Это убегает select
создать. Сводка break
то, что Вы добираетесь, когда Вы работаете help break
только упоминания, что это убегает for
, while
, или until
циклы, поэтому возможно, Вы ожидали, что это повредит внешнее while
цикл. Однако сводка select
Вы добираетесь, когда Вы работаете help select
разъясняет вопрос:
КОМАНДЫ выполняются после каждого выбора, пока не выполняется команда прерывания работы.
Пользователь вводит что-либо кроме 1
, 2
, или 3
. Так ни одно из выполнений случаев. Второе break
команда, после esac
, выполнения. Это также повреждается select
создайте, не while
цикл, и таким образом, while
цикл работает снова.
select
на самом деле цикл. Ваш break
команды повреждаются select
вместо внешнего while
. Учитывая описание проблемы Вы, если, у Вас почти наверняка нет причины использовать внешний цикл. Таким образом, одно хорошее решение было бы, чтобы Вы изменили внешнее while
в if
. Чтобы сделать это, Вы также должны будете:
do
в a then
.done
в a fi
.Если Вы выберете это решение, то Вы также захотите переместить некоторые команды, которые Вы в настоящее время имеете вне while
(который должен быть if
) так, чтобы они были в нем. Прямо сейчас пользователю предлагают выбрать опцию, даже если никакие меры не были бы на самом деле приняты. Та дополнительная ошибка не была бы исправлена, просто изменившись while
к if
(и внесение других двух необходимых изменений для этого для работы).
Альтернативное решение состоит в том, чтобы заставить Ваш сценарий выйти рано если [ -e "$sourceFile" ]
ложь. Один способ сделать, который является:
[ -e "$sourceFile" ] || exit
Другой, если Вы предпочитаете использовать if
:
if ! [ -e "$sourceFile" ]; then
exit
fi
При использовании любого из тех то остальная часть кода - кода, который Вы намереваетесь выполнить, только если исходный файл существует - не должна была бы быть включена ни в какую управляющую структуру. Обратите внимание, что Вы все еще захотите, чтобы это прибыло прежде, а не после, команды, которые предлагают пользователю какой действие взять.
Обратите внимание, что Вы могли "исправить" свой код путем замены Вашего break
команды с exit
. Вы могли также "зафиксировать" его путем передачи числового аргумента break
сказать этому сколько уровней вложения убегать (большинство языков break
команды не поддерживают это, но Bash делает). Однако я рекомендую против использования любого из тех подходов - кроме, возможно, к только для испытания его - потому что Вы добавили бы больше сложности для кодирования, который должен вместо этого быть зафиксирован путем создания этого более простым. В настоящее время Вы используете a while
цикл для чего-то, где никакой цикл не имеет смысл, поэтому однако, Вы решаете проблему, это должно быть способом, который позволяет Вам упростить код, не делая это.
Если с другой стороны, Вы действительно предназначаете все это для выполнения много раз, то необходимо рассмотреть, какое условие значительно нарушило бы внешний цикл. Например, возможно, Вы означали запрашивать источник и целевые файлы в каждом повторении внешнего цикла. Если так, затем необходимо будет изменить код, чтобы сделать это.
Наконец, я рекомендую форматировать Ваш код таким способом, которым, когда управляющая структура охватывает несколько строк, строка, которая открывает его и строка, которая закрывается, он располагается с отступом на том же уровне и строках в нем (кроме случайных ситуаций, где невозможно сделать так), располагаются с отступом больше. Тем путем Вы будете знать который fi
соответствия, который if
, который done
соответствия, который while
/until
/for
/select
, и который esac
соответствия, который case
. Способностью распознать, что более легко, Вы также сможете лучше определить, когда необходимое ключевое слово будет отсутствовать, и путем расположения с отступом содержания последовательным способом, Вы сможете лучше определить, когда логика, если Ваш сценарий будет отличаться от того, что Вы предназначаете.