Сценарий Bash для перезаписи / добавления файла назначения с меню параметров [дубликат]

На этот вопрос уже есть ответ здесь:

Я пытаюсь написать 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
-2
задан 23 April 2018 в 20:33

1 ответ

Поскольку Вы заявили это, проблема, которую Вы пытаетесь решить, (добавленный акцент):

Я пытаюсь записать сценарий удара для запроса пользователя имя файла, и если файл существует, позвольте им перезаписывать или добавлять файл.

Любопытно, код в Вашем сценарии, который проверяет, существует ли файл, не использует if, хотя это, вероятно, должно. Вместо этого это использует while:

while [ -e "$sourceFile" ]; do

Это - цикл. Если исходный файл существует, все в том цикле, до соответствия

done

на последней строке Ваших выполнений сценария. Это - a while цикл, поэтому после того, как это запустит в первый раз тест, выполняется снова. Если файл все еще существует, тело цикла работает снова, и так далее, и так далее, и так далее.

Но ничто в теле цикла никогда не заставляет файл останавливаться существующий. Эти четыре возможности:

  1. Пользователь вводит a 1 и исходный файл копируется по целевому файлу. Это скопировано, не перемещено, таким образом, исходный файл все еще существует с тем же именем.

  2. Пользователь вводит a 2 и содержание исходного файла добавляется в целевой файл. Однако исходный файл не удален; это все еще там.

  3. Пользователь вводит a 3 и a Script Terminated сообщение печатается. Это сразу сопровождается a break команда. Это убегает select создать. Сводка break то, что Вы добираетесь, когда Вы работаете help break только упоминания, что это убегает for, while, или until циклы, поэтому возможно, Вы ожидали, что это повредит внешнее while цикл. Однако сводка select Вы добираетесь, когда Вы работаете help select разъясняет вопрос:

    КОМАНДЫ выполняются после каждого выбора, пока не выполняется команда прерывания работы.

  4. Пользователь вводит что-либо кроме 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. Способностью распознать, что более легко, Вы также сможете лучше определить, когда необходимое ключевое слово будет отсутствовать, и путем расположения с отступом содержания последовательным способом, Вы сможете лучше определить, когда логика, если Ваш сценарий будет отличаться от того, что Вы предназначаете.

4
ответ дан 30 October 2019 в 01:23

Другие вопросы по тегам:

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