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

よりエレガントなソリューションが公開されていますが、元のスクリプトの失敗につながったいくつかのエラーとそれを解決する方法を指摘することが重要だと思いました。

まず、whileループで変数をテストするときに変数に格納されている実際のデータを読み取るには、変数を変数の前にpackage1配置する必要があります。$

パターンマッチングにワイルドカードを使用することができるので、whileループテスト内で[[...]]代わりにnextを使用してください。しかし、これはshではなくbashでのみ機能します。より[...]*これ[[...]][...]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

ユーザーにアイテムを選択させたい場合既存のファイルについてユーザーが完全に知らないファイル名を作成するのではなく、リストから選択できるようにするには、selectを使用します。read

select package1 in *.zip; do
    break;
done
echo "$package1"

ユーザーはリストを表示して番号を入力します。

関連情報