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 루프 테스트 [[...]]대신 [...]에 사용하세요. 이렇게 하면 와일드카드를 사용하여 패턴 일치를 수행할 수 있습니다 *. 그러나 이것은 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명령(조건문의 일부가 아닌)이 0이 아닌 종료 코드와 함께 반환되면 자동으로 종료됩니다.

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"

사용자에게 목록이 표시되고 번호를 입력합니다.

관련 정보