[validation] Bash 스크립트에 대한 매개 변수 유효성 검사

필요하지 않게되는 여러 폴더를 제거하는 프로세스를 자동화하는 데 도움이되는 기본 폴더를 생각해 냈습니다.

#!/bin/bash
rm -rf ~/myfolder1/$1/anotherfolder
rm -rf ~/myfolder2/$1/yetanotherfolder
rm -rf ~/myfolder3/$1/thisisafolder

이것은 다음과 같이 유발됩니다.

./myscript.sh <{id-number}>

문제는 id-number (그때처럼) 입력하는 것을 잊으면 정말로 삭제하고 싶지 않은 많은 것을 잠재적으로 삭제할 수 있다는 것입니다.

명령 줄 매개 변수에 모든 형태의 유효성 검사를 추가 할 수있는 방법이 있습니까? 제 경우에는 a) 하나의 매개 변수가 있는지, b) 숫자인지, c) 해당 폴더가 있는지 확인하는 것이 좋습니다. 스크립트를 계속하기 전에.



답변

#!/bin/sh
die () {
    echo >&2 "$@"
    exit 1
}

[ "$#" -eq 1 ] || die "1 argument required, $# provided"
echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided"

while read dir
do
    [ -d "$dir" ] || die "Directory $dir does not exist"
    rm -rf "$dir"
done <<EOF
~/myfolder1/$1/anotherfolder
~/myfolder2/$1/yetanotherfolder
~/myfolder3/$1/thisisafolder
EOF

편집 : 처음에는 디렉토리가 존재하는지 확인하는 부분을 놓쳐서 스크립트를 완성했습니다. 또한 의견에서 제기 된 문제를 해결했습니다. 정규식 고정로부터 스위치 ==eq.

내가 말할 수있는 한 이것은 이식 가능한 POSIX 호환 스크립트 여야합니다. 이 때문에 실제로 중요하다 어떤 bashisms, 사용하지 않는 /bin/sh우분투에 실제로 dash,이 일하지 bash.


답변

sh솔루션은 Brian Campbell고상하고 잘 실행되었지만 몇 가지 문제가 있으므로 나만의 bash솔루션을 제공 할 것이라고 생각했습니다 .

sh하나 의 문제 :

  • 의 물결표는 ~/fooheredocs 내부의 홈 디렉토리로 확장되지 않습니다. 그리고 read성명 에서 읽 거나 성명에서 인용 할 때도 마찬가지 rm입니다. 즉, No such file or directory오류가 발생합니다.
  • grep기본 작업을 위해 분기하는 등은 멍청합니다. 특히 bash의 “무거운”무게를 피하기 위해 엉뚱한 셸을 사용할 때.
  • 또한 몇 가지 인용 문제를 발견했습니다. 예를 들어 그의 echo .
  • 드물지만 솔루션은 줄 바꿈이 포함 된 파일 이름을 처리 할 수 ​​없습니다. (거의 어떤 솔루션도 sh그것들에 대처할 수 없습니다 -이것이 제가 거의 항상 선호하는 이유 bash입니다. 잘 사용하면 훨씬 더 방탄하고 악용하기 더 어렵습니다).

그렇습니다. /bin/sh해시 뱅에 사용한다는 것은 어떤 대가를 치르더라도 ISMS를 피해야한다는 것을 의미 하지만, 우분투 또는 정직하고 솔직한 경우에도 원하는 bash모든 ISMS 를 사용할 수 있습니다.bash#!/bin/bash 정상에 .

그래서 여기에 bash더 작고, 더 깨끗하고, 더 투명하고, 아마도 “더 빠르며”더 방탄 한 솔루션이 있습니다.

[[ -d $1 && $1 != *[^0-9]* ]] || { echo "Invalid input." >&2; exit 1; }
rm -rf ~/foo/"$1"/bar ...
  1. 주위의 따옴표에 주목하십시오 $1.rm 문!
  2. 다음의 -d경우에도 검사가 실패합니다.$1 비어 그 하나에 두 개의 검사를, 그래서.
  3. 나는 이유 때문에 정규 표현식을 피했습니다. =~bash에서 사용해야하는 경우 정규식을 변수에 넣어야합니다. 어쨌든 저와 같은 glob은 항상 선호되며 훨씬 더 많은 bash 버전에서 지원됩니다.

답변

나는 bash를 사용할 것입니다 [[.

if [[ ! ("$#" == 1 && $1 =~ ^[0-9]+$ && -d $1) ]]; then
    echo 'Please pass a number that corresponds to a directory'
    exit 1
fi

이 FAQ 가 좋은 정보 소스 라는 것을 알았습니다 .


답변

위의 답변만큼 방탄하지는 않지만 여전히 효과적입니다.

#!/bin/bash
if [ "$1" = "" ]
then
  echo "Usage: $0 <id number to be cleaned up>"
  exit
fi

# rm commands go here


답변

사용 set -u설정되지 않은 인수를 참조 즉시 스크립트를 실패합니다.

기사 : 강력한 Bash 쉘 스크립트 작성-David Pashley.com을 참조하십시오 .


답변

test ( man test) 의 man 페이지 는 bash에서 부울 연산자로 사용할 수있는 모든 연산자를 제공합니다. 다른 프로그래밍 언어에서와 마찬가지로 입력 유효성 검사를 위해 스크립트 (또는 함수) 시작 부분에 이러한 플래그를 사용합니다. 예를 들면 :

if [ -z $1 ] ; then
  echo "First parameter needed!" && exit 1;
fi

if [ -z $2 ] ; then
  echo "Second parameter needed!" && exit 2;
fi


답변

빈 문자열을 테스트하려면 ‘-z’를 사용하고 디렉토리를 확인하려면 ‘-d를 사용하십시오.

if [[ -z "$@" ]]; then
    echo >&2 "You must supply an argument!"
    exit 1
elif [[ ! -d "$@" ]]; then
    echo >&2 "$@ is not a valid directory!"
    exit 1
fi