我正在調整一個腳本,以便它會詢問用戶特定類型的文件。如果輸入的檔案與特定檔案類型不匹配,則進入 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
文件(或提示的任何文件類型)可能位於任何其他目錄中怎麼辦?我希望它能夠在 shell 中提供更改目錄的選項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。請參見這[[...]]
回答使用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 存檔檔案的路徑名來呼叫您的腳本。這允許他們使用 shell 的檔案名稱完成工具和檔案名稱通配模式。
該腳本將使用例如調用
./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"
用戶將看到一個清單並輸入號碼。