スクリプトを調整して、ユーザーに特定の種類のファイルを要求するようにしています。入力されたファイルが特定のファイルの種類と一致しない場合は、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ループテストで[[...]]
の代わりに を使用します。[...]
これにより、ワイルドカードを使用してパターンマッチングを行うことができます*
。ただし、これは bash でのみ機能し、sh では機能しません。これ[[...]]
versusの使用に関する詳細な説明については、回答を参照してください[...]
。
<<< 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"
ユーザーにはリストが表示され、番号を入力します。