Я настраиваю скрипт так, чтобы он запрашивал у пользователя файл определенного типа. Если введенный файл не соответствует определенному типу файла, он переходит в цикл while и повторяется до тех пор, пока пользователь не введет правильный файл.
В этом случае я запрашиваю у пользователя файл .zip
в:
read -p "Enter zip file: " package1
while [ package1 != *.zip ] ; do
read -p "Please enter file ending in '.zip': " package1
done <<< package1
echo $package1
У меня были ошибки до этого момента. Теперь я получаю только пустой курсор, без вывода. Независимо от того, ввожу я *.zip
или нет, он переходит на следующую строку с пустым курсором и без вывода.
Мысли?
РЕДАКТИРОВАТЬ:
Хорошо, я решил остановиться на select
петле, и это гораздо лучший вариант, чем while
в данном случае.
Но что, если этот zip
файл (или любой другой тип файла, который был предложен) может находиться в любом другом каталоге? Я хочу, чтобы он давал возможность менять каталоги, находясь в оболочке select-loop
.
Я попробовал:
echo Select zip file:
options=(".." *.zip)
select package1 in "${options[@]}" ; do
case $package1 in
1 ) cd ..; echo Select zip file: ;;
# Different Directory ) ;;
* ) break ;;
esac
done
Но цикл не будет повторно отображать пункты меню после смены каталогов. Я не уверен, как предложить пользователю cd
совершенно другой путь, кроме того, ../
который он хочет, или что использовать для
"All other existing \# file items" ) ... ; break;;
Внутриcase
решение1
Упростим задачу логически, изучив только последнее расширение:
while [ "${package1##*.}" != "zip" ]
do
read -e -p "Specify a .zip file: " package1
done
echo $package1
решение2
Было опубликовано более элегантное решение, но я считаю важным указать на некоторые ошибки, которые приводят к сбою вашего исходного скрипта, и на то, как их исправить.
Во-первых, когда вы проверяете переменную package1
в цикле while, вам нужно поместить $
перед ней оператор , чтобы прочитать фактические данные, хранящиеся в этой переменной.
Далее используйте [[...]]
вместо [...]
в вашем тесте цикла while, так как это позволяет вам выполнять сопоставление с образцом с использованием вашего подстановочного знака *
. Однако это работает только в bash, а не в sh. Пожалуйста, см.этотответьте на подробное объяснение использования [[...]]
vs.[...]
Наконец, вам не нужно передавать строку <<< package1
в конце цикла while.
Вот измененная версия вашего скрипта, которая работает так, как задумано.
#!/bin/bash
read -p "Enter zip file: " package1
while [[ "$package1" != *.zip ]]; do
read -p "Please enter file ending in '.zip': " package1
done
echo $package1
решение3
Никогда не заставляйте пользователя вводить пути к файлам в интерактивном режиме. Им проще вызвать ваш скрипт с путями к файлам Zip-архива в командной строке скрипта. Это позволяет им использовать функцию завершения имени файла и шаблоны подстановки имени файла оболочки.
Скрипт будет вызываться с помощью, например,
./myscript /some/path/myarchive.zip
или
./myscript folder/archive-*.zip
или похожие.
В сценарии вы бы сделали следующее:
#!/bin/bash
for archive_path do
printf 'Processing archive "%s"...\n' "$archive_path"
# code to process "$archive_path" goes here
done
Цикл в скрипте будет перебирать все аргументы, переданные скрипту, и в каждой итерации "$archive_path"
будет содержать путь к отдельному архиву, переданному скрипту.
Нет необходимости проверять, "$archive_path"
заканчивается ли имя файла какой-либо конкретной строкой, так как инструменты, которые вы будете использовать в архиве, могут даже не заботиться о суффиксе имени файла. Если они это сделают, то они завершатся с соответствующим кодом выхода, который вы легко сможете поймать:
if ! unzip "$archive_path"; then
printf 'Failed to run unzip on "%s"\n' "$archive_path" >&2
exit 1
fi
Если вы используете его set -e
в скрипте (вероятно, в качестве его первого оператора), он автоматически завершит работу, когда любая команда (не являющаяся частью условного оператора) вернет ненулевой код выхода.
set -e
# The following would terminate the script if it failed:
unzip "$archive_path"
Что касается вашего добавленного "редактирования": то, что вы делаете, это начало реализации инструмента просмотра файлов или файлового менеджера для выбора Zip-архивов. В зависимости от того, для чего вы на самом деле хотите использовать этот код, это может быть излишним.
решение4
Если вы хотите, чтобы пользователь выбрал один из вариантовсуществующийfiles, я бы использовал select
вместо read
, чтобы позволить пользователю выбирать из списка, вместо того чтобы писать имя файла, которое он может точно не знать.
select package1 in *.zip; do
break;
done
echo "$package1"
Пользователю будет представлен список, и он должен будет ввести номер.