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스크립트에서(아마도 첫 번째 명령문으로) 이를 사용하는 경우 명령(조건문의 일부가 아님)이 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"

사용자는 목록을 보고 번호를 입력합니다.

관련 정보