Запросить у пользователя тип файла в цикле while

Запросить у пользователя тип файла в цикле while

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

Пользователю будет представлен список, и он должен будет ввести номер.

Связанный контент