= Skeleton Filter Program in Bash = [[TableOfContents]] ÀÌ ±ÛÀº bash¸¦ ½á¼­ DevelFilterSkeleton¿¡¼­ ´Ù·é ÇÊÅÍ ÇÁ·Î±×·¥ÀÇ »À´ë¸¦ ¸¸µå´Â ¹ýÀ» ¼Ò°³ÇÕ´Ï´Ù. DevelFilterSkeletonÀ» ÀÐÁö ¾Ê¾Ò´Ù¸é ¸ÕÀú ±× ±ÛÀ» ÀÐÀ¸½Ã±â ¹Ù¶ø´Ï´Ù. (ÁÖÀÇ: ÀÌ ±ÛÀº bash shell script¸¦ ¾²´Â ¹ýÀ» ÀÚ¼¼È÷ ¼Ò°³ÇÏ´Â ±ÛÀÌ ¾Æ´Õ´Ï´Ù.) == Output Messages == ÇÊÅÍ ÇÁ·Î±×·¥Àº ¾î¶² »óȲÀÌ ¹ß»ýÇßÀ» ¶§, »ç¿ëÀÚ¿¡°Ô º¸°íÇϰųª, ¿¡·¯¸¦ Ãâ·ÂÇÒ ¶§°¡ Á¾Á¾ ¹ß»ýÇϱ⠶§¹®¿¡, °æ°í ¶Ç´Â ¿¡·¯ ¸Þ½ÃÁö¸¦ ³» º¸³»´Â °æ¿ì°¡ ÀÖ½À´Ï´Ù. ÇÊÅÍ ÇÁ·Î±×·¥Àº ±âº»ÀûÀ¸·Î ó¸®ÇÑ µ¥ÀÌÅ͸¦ Ç¥ÁØ Ãâ·ÂÀ» ÅëÇØ ³» º¸³»¹Ç·Î, ÀÌ·± ¸Þ½ÃÁöµéÀ» Ç¥ÁØ ÀÔ·ÂÀ¸·Î º¸³½´Ù¸é, µ¥ÀÌÅÍ¿Í ¼¯ÀÏ °æ¿ì°¡ Àֱ⠶§¹®¿¡ ´ëºÎºÐ Ç¥ÁØ Ãâ·ÂÀ» ½á¼­ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÕ´Ï´Ù. DevelFilterCSkeleton¿¡¼­´Â ½Ã½ºÅÛ ÇÔ¼ö È£Ãâ ÈÄ ÀÏÀÏÈ÷ Àü¿ª º¯¼ö errnoÀÇ °ªÀ» Á¶»çÇؼ­ strerror(3)¸¦ ½á¼­ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇßÁö¸¸, shell script¿¡¼­´Â ±×·² ÇÊ¿ä°¡ ¾ø½À´Ï´Ù. º¸Åë ÇÁ·Î±×·¥ÀÌ ³¡³ª¸é ÀϹÝÀûÀ¸·Î ¼º°øÀûÀ¸·Î ³¡³µÀ» ¶§ 0À», ½ÇÆÐÇßÀ» °æ¿ì¿¡´Â 0ÀÌ ¾Æ´Ñ °ªÀ» ¸®ÅÏÇÏ°Ô µË´Ï´Ù. ÀÌ °ªÀ» exit status¶ó°í ÇÏ°í, ¹Ù·Î Àü ÇÁ·Î±×·¥ÀÇ exit status´Â Ç×»ó º¯¼ö $?¿¡ ÀúÀåµÇ¾î ÀÖ½À´Ï´Ù. ¾Æ·¡¿¡ ±× ¿¹¸¦ º¸ÀÔ´Ï´Ù. {{{#!vim sh $ ls *txt a.txt a1.txt a2.txt a3.txt readme.txt $ echo $? 0 $ ls -y ls: invalid option -- y Try `ls --help' for more information. $ echo $? 1 $ _ }}} ÇÁ·Î±×·¥ÀÇ ¼º°ø ¿©ºÎ´Â À§¿Í °°ÀÌ È®ÀÎÇÒ ¼ö ÀÖÀ¸¹Ç·Î, ¿ì¸®´Â DevelFilterSkeleton¿¡¼­ ´Ù·é ÀϹÝÀûÀÎ °ü½À¿¡ µû¶ó ¿¡·¯ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇØ¾ß ÇÕ´Ï´Ù. º¸Åë ¸¹Àº shell script °³¹ßÀÚµéÀÌ ¿¡·¯ ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÒ ¶§, °¡Àå ¸¹ÀÌ ¾²´Â ¹æ¹ýÀº ´ÙÀ½°ú °°ÀÌ ÇÏ´Â °ÍÀÔ´Ï´Ù: {{{#!vim sh echo "error: description" exit 1 }}} ±×·¯³ª ÀÌ ¹æ½ÄÀº ÇÊÅÍ ÇÁ·Î±×·¥ÀÌ °®Ãç¾ß ÇÒ ¸î °¡Áö¸¦ ¾î±â°í ÀÖ½À´Ï´Ù. ù°, ÇÁ·Î±×·¥ À̸§À» Ãâ·ÂÇÏÁö ¾Ê¾Ò½À´Ï´Ù. µÑ°, echo´Â Ç¥ÁØ Ãâ·ÂÀ¸·Î ¹ÞÀº ÀÎÀÚµéÀ» Ãâ·ÂÇϱ⠶§¹®¿¡, ¸Þ½ÃÁö´Â Ç¥ÁØ ¿¡·¯·Î Ãâ·ÂÇÑ´Ù´Â °ü½ÀÀ» ¾î°å½À´Ï´Ù. ±×·¯¹Ç·Î ¿ì¸®´Â ÀÌ µÎ °¡Áö¸¦ ÇØ°áÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¾Ë¾Æº¸·Á°í ÇÕ´Ï´Ù. ¸ÕÀú Ç×»ó ¿ì¸® ÇÁ·Î±×·¥ À̸§À» ´ÙÀ½°ú °°Àº º¯¼ö¿¡ ÀúÀåÇØ ³õ±â·Î ÇսôÙ: {{{#!vim sh program_name='foo' }}} Âü°í, º¯¼ö $0¿¡ ´ã±ä À̸§À» Á÷Á¢ ¾µ ¼öµµ ÀÖÁö¸¸, ÀÌ À̸§Àº shell¿¡ µû¶ó¼­ ´Ù¸£°Ô ÀúÀåµÉ ¼ö ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î "/usr/bin/foo"°¡ µÉ ¼öµµ ÀÖ°í, "foo"°¡ µÉ ¼öµµ Àֱ⠶§¹®¿¡, ÀÏ°ü¼ºÀ» À¯ÁöÇϱâ À§ÇØ, µû·Î ÀúÀåÇØ ³õ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. ±×¸®°í ³ª¼­ ¾î¶² ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÏ·Á°í ÇÒ ¶§, ´ÙÀ½°ú °°ÀÌ ÇÒ ¼ö ÀÖ½À´Ï´Ù: {{{#!vim sh echo "$program_name: description" exit 1 }}} ¾ÆÁ÷±îÁö´Â ¸ðµÎ Ç¥ÁØ Ãâ·ÂÀ¸·Î ¸Þ½ÃÁö°¡ 󸮵Ǿú½À´Ï´Ù. ÀÌÁ¦ ÀÌ ¿¡·¯ ¸Þ½ÃÁö¸¦ Ç¥ÁØ ¿¡·¯·Î º¸³»·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÏ¸é µË´Ï´Ù: {{{#!vim sh echo "$program_name: description" 1>&2 exit 1 }}} ÀÌÁ¦ ÀÌ ±â´ÉÀ» Æí¸®ÇÏ°Ô ¾µ ¼ö ÀÖµµ·Ï ÇÔ¼ö·Î ¸¸µé¾î µî·ÏÇÕ´Ï´Ù: {{{#!vim sh function error() { echo "$program_name" "$@" 1>&2 exit 1 } }}} ±×·±µ¥, »óȲ¿¡ µû¶ó¼­ °æ°í ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÏ°Ô ÇÏ·Á¸é, À§¿Í °°ÀÌ Á¤ÀÇÇÑ error()¸¦ ¾µ ¼ö ¾ø½À´Ï´Ù. ¿Ö³ÄÇϸé error()´Â ¹Ù·Î exit 1¸¦ ºÒ·¯¼­ ÇÁ·Î±×·¥À» ³¡³»¹ö¸®±â ¶§¹®ÀÔ´Ï´Ù. µû¶ó¼­ ¿ì¸®´Â error()ÀÇ Ã¹¹ø° ÀÎÀÚ¸¦ exit status·Î ¾²±â·Î ÇÏ°í, ÀÌ °ªÀÌ 0ÀÌ ¾Æ´Ò °æ¿ì exit¸¦ È£ÃâÇϵµ·Ï ÇÕ´Ï´Ù: {{{#!vim sh function error () { status="$1" shift; echo "$progra_name" "$@" 1>&2 if [ 0 -ne "$status" ]; then exit "$status"; fi } }}} À§ ÇÔ¼ö¸¦ ¾²´Â ¿¹¸¦ º¸ÀÌ¸é ¾Æ·¡¿Í °°½À´Ï´Ù: {{{#!vim sh error 1 cannot open file $INPUT. error 0 cannot open file $INIT_FILE. }}} ù¹ø° ¿¹´Â "$INPUT"À̶ó´Â ÆÄÀÏÀ» ¿­ ¼ö ¾ø´Ù°í Ç¥ÁØ ¿¡·¯·Î ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÏ°í ÇÁ·Î±×·¥À» Á¾·áÇÕ´Ï´Ù. µÎ¹ø° ¿¹´Â "$INIT_FILE"À̶ó´Â ÆÄÀÏÀ» ¿­ ¼ö ¾ø´Ù°í Ç¥ÁØ ¿¡·¯·Î ¸Þ½ÃÁö¸¦ Ãâ·ÂÇϱ⸸ ÇÕ´Ï´Ù. error()´Â ù ¹ø° ÀÎÀÚ¸¦ exit status·Î ¾²°í ³ª¸ÓÁö ÀÎÀÚ´Â ¸ðµÎ Ç¥ÁØ ¿¡·¯·Î Ãâ·ÂÇϱ⠶§¹®¿¡, ÀÌ ÇÔ¼öÀÇ »ç¿ëÀÚ°¡ ½Ç¼öÇÏÁö ¾Êµµ·Ï, ÁÖ¼®µµ Ãß°¡ÇÏ°í, º¯¼ö program_nameÀÌ Á¤ÀǵǾî ÀÖÀ» ¶§¿¡¸¸ "$program_name: "À» Ãâ·ÂÇϵµ·Ï °íÄ¡¸é ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim sh function error() { # usage: error EXIT_STATUS MESSAGE... # Print MESSAGE to the standard error (stderr) and call `exit EXIT_STATUS' # if EXIT_STATUS is nonzero. status="$1" shift; if [ -n "$program_name" ]; then echo -n "$program_name: " fi echo "$@" 1>&2 if [ 0 -ne "$status" ]; then exit "$status" fi } }}} º¸Åë ´É¼÷ÇÑ shell ÇÁ·Î±×·¡¸ÓµéÀº À§¿Í °°ÀÌ "if Á¶°Ç-¹®Àå then ½ÇÇà-¹®Àå fi" ¹®Àå¿¡¼­ Á¶°Ç-¹®ÀåÀÌ ÂüÀÏ °æ¿ì, ½ÇÇà-¸í·ÉÀ» ¼öÇàÇ϶ó´Â Äڵ带 "Á¶°Ç-¹®Àå && ½ÇÇà-¹®Àå" ÇüÅ·Π¾²°ï ÇÕ´Ï´Ù. ±×·¸°Ô °íÃÄ º¸¸é ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim sh function error () { # usage: error EXIT_STATUS MESSAGE... # Print MESSAGE to the standard error (stderr) and call `exit EXIT_STATUS' # if EXIT_STATUS is nonzero. status="$1" shift; test -n "$program_name" && echo -n "$program_name: " 1>&2 echo "$@" 1>&2 test 0 -ne "$status" && exit "$status"; } }}} ¶Ç, error() ÇÔ¼ö´Â ¸ðµç Ãâ·ÂÀÌ Ç¥ÁØ ¿¡·¯·Î Ãâ·ÂµÇ±â ¶§¹®¿¡, ¸í·É °¢°¢¿¡ "1>&2"¶ó´Â redirectionÀ» ¾²Áö ¸»°í, ÇÔ¼ö ÀÚüÀÇ Ç¥ÁØ Ãâ·ÂÀ» Ç¥ÁØ ¿¡·¯·Î redirectionÇÏ´Â °ÍÀÌ Á» ´õ ±ò²ûÇÕ´Ï´Ù. ÄÚµå´Â ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim sh function error () { # usage: error EXIT_STATUS MESSAGE... # Print MESSAGE to the standard error (stderr) and call `exit EXIT_STATUS' # if EXIT_STATUS is nonzero. status="$1" shift; test -n "$program_name" && echo -n "$program_name: " echo "$@" test 0 -ne "$status" && exit "$status"; } 1>&2 }}} == Option Processing == Á÷Á¢ ó¸®ÇÏ´Â °ÍÀº ±ÍÂú¾Æ¼­ ÇÏÁö ¾Ê½À´Ï´Ù. Bash¿¡¼­ ¾µ ¼ö ÀÖ´Â, ¿É¼Ç 󸮸¦ µµ¿ÍÁÖ´Â ¸í·ÉÀº µÎ °³°¡ Àִµ¥, Çϳª´Â bash ÀÚü¿¡¼­ Á¦°øÇÏ´Â getoptsÀÌ°í, Çϳª´Â ¿ÜºÎ ¸í·ÉÀ¸·Î Á¸ÀçÇÏ´Â getopt(1)ÀÔ´Ï´Ù. === Using Built-in getopts === Bash¿¡ ³»ÀåµÇ¾î ÀÖ´Â getopts´Â ªÀº ¿É¼Ç¸¸ ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¸ÕÀú µµ¿ò¸»À» Ãâ·ÂÇÏ°í Á¾·áÇÏ´Â ÇÔ¼öÀÎ help_and_exit()°¡ Á¤ÀǵǾî ÀÖ°í, ¹öÀüÀ» Ãâ·ÂÇÏ°í Á¾·áÇÏ´Â version_and_exit()°¡ Á¤ÀǵǾî ÀÖ´Ù°í ÇÏ°í, ¾Æ·¡ Äڵ带 º¸±â ¹Ù¶ø´Ï´Ù: {{{#!vim sh while getopts "hvo:q" opt; do case $opt in '?') error 1 "Try \`-h' for more information" ;; 'h') help_and_exit ;; 'v') version_and_exit ;; 'o') output_filename=$OPTARG; ;; 'q') verbose_mode=0 ;; *) error 1 "Internal getopts error" ;; esac done shift `expr $OPTIND - 1` }}} getopts´Â ºÎ¸¦ ¶§¸¶´Ù ÇϳªÀÇ ¿É¼ÇÀ» ó¸®ÇÕ´Ï´Ù. ´õ ÀÌ»ó ó¸®ÇÒ ¿É¼ÇÀÌ ¾øÀ¸¸é nonzero °ªÀ», ÀÖ¾úÀ¸¸é 0À» ¸®ÅÏÇÕ´Ï´Ù. (µû¶ó¼­ while ¹®ÀåÀ» ½á¼­ ´Ù ¿É¼ÇÀ» ó¸®ÇÒ ¶§±îÁö ¹Ýº¹Çؼ­ ºÒ·¯ÁÝ´Ï´Ù.) ù¹ø° ÀÎÀÚ´Â ¹Þ¾ÆµéÀÏ ¿É¼ÇÀÇ Á¾·ùÀÔ´Ï´Ù. ¿©±â¼­ ÇÑ ±ÛÀÚ°¡ ÇϳªÀÇ ¿É¼Ç¿¡ ÇØ´çÇϸç, ¿É¼ÇÀÌ ÀÎÀÚ¸¦ ¹ÞÀ» °æ¿ì, ±× ¿É¼Ç ±ÛÀÚ µÚ¿¡ ':'¸¦ ºÙ¿© ÁÝ´Ï´Ù. µû¶ó¼­ À§ÀÇ °æ¿ì ó¸®ÇÏ´Â ¿É¼ÇÀº '-h', '-v', '-q', '-o arg'ÀÔ´Ï´Ù. getoptsÀÇ µÎ¹ø° ÀÎÀÚ´Â, getopts°¡ ó¸®ÇÑ ¿É¼Ç ±ÛÀÚ¸¦ ÀúÀåÇÏ´Â º¯¼ö À̸§ÀÔ´Ï´Ù. ÀÌ´Â ³ªÁß¿¡ case ¹®¿¡¼­ ½ÇÁ¦ ¾î¶² ¿É¼ÇÀÌ µé¾î¿Ô´ÂÁö¸¦ ó¸®Çϴµ¥¿¡ ¾²ÀÔ´Ï´Ù. getopts°¡ ó¸®ÇÒ ¼ö ¾ø´Â ¿É¼ÇÀÌ µé¾î¿Â °æ¿ì¿¡´Â, getoptsÀÇ ¼¼¹ø° ÀÎÀÚ¿¡ '?'¸¦ ³Ö¾îÁÝ´Ï´Ù. À§¸¦ º¸¸é ¾Ë°ÚÁö¸¸, ¿ì¸®´Â ÀÌ ¿¡·¯¸¦ ó¸®ÇØ¾ß ÇÕ´Ï´Ù. ¿É¼ÇÀÌ ÀÎÀÚ¸¦ °¡Áö°í ÀÖ´Â °æ¿ì, ¿ì¸®´Â OPTARG¶ó´Â º¯¼ö¸¦ ÅëÇØ ±× ÀÎÀÚ¸¦ ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¶ÇÇÑ getopts°¡ ¸ðµç ÀÛ¾÷À» ³¡³ÂÀ» °æ¿ì, ¿ì¸®´Â OPTIND¸¦ ÅëÇؼ­, ¿É¼ÇÀÌ ¾Æ´Ñ ÀÎÀÚÀÇ À§Ä¡¸¦ ¾Ë ¼ö ÀÖ½À´Ï´Ù. À§ Äڵ忡¼­ ¸Ç ¸¶Áö¸· shift¿¡¼­ OPTIND°¡ ¾²ÀÎ °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. === Using external getopt === getopt(1)Àº ´ëºÎºÐ ¸®´ª½º ¹èÆ÷ÆÇ¿¡ Æ÷ÇԵǾî ÀÖ½À´Ï´Ù. (¾øÀ¸¸é µû·Î ¼³Ä¡ÇØ¾ß Çϴµ¥, ¾Æ·¡¸¦ Âü°íÇϽñ⠹ٶø´Ï´Ù. ÀÌ ¸í·ÉÀÌ ±âº»ÀûÀ¸·Î ¼³Ä¡µÇ¾î ÀÖÁö ¾Ê´Â ¹èÆ÷ÆÇÀº ¾øÀ» °ÍÀÔ´Ï´Ù. * Gentoo: util-linux ÆÐÅ°Áö¿¡ ÀÖ½À´Ï´Ù. "emerge util-linux"¸¦ ½ÇÇà * Redhat ¶Ç´Â Fedora Core: util-linux ÆÐÅ°Áö¿¡ ÀÖ½À´Ï´Ù "rpm -Uvh util-linux-*.rpm"¸¦ ½ÇÇà * Debian: {{{#red TODO}}}: '''´©°¡ ä¿ö ÁÖ¼¼¿ä!!!''' * S''''''uSE: {{{#red TODO}}}: '''´©°¡ ä¿ö ÁÖ¼¼¿ä!!!''' * ±×¿Ü: [http://www.kernel.org/pub/linux/utils/util-linux/ ¿©±â]¿¡¼­ ¹Þ¾Æ¼­ ¼³Ä¡ÇÏ¸é µË´Ï´Ù. getopt(1)¸¦ ¾²¸é C ÇÔ¼ö getopt_long(3)À» ¾´ °Í°ú °°ÀÌ, ±ä ¿É¼ÇµéÀ» ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. {{{#red TODO}}}: blah... blah... À½.. ÀÏÇϱ⠽Ⱦ ¾²±â ½ÃÀÛÇÑ ±ÛÀε¥.. ±ÍÂú³×¿ä.. :-) ³ªÁß¿¡ ¾²°Ú½À´Ï´Ù. == Source Listings == ±Û¾´ÀÌ´Â Ç×»ó ÀÌ »À´ë Äڵ带 ÃÖ½ÅÀ¸·Î ¸¸µé·Á°í ÇÏ°í ÀÖ½À´Ï´Ù. ÃֽŠÄÚµå´Â ±Û¾´ÀÌÀÇ CVS [http://www.cinsk.org/cgi-bin/viewcvs.cgi CVS]¿¡¼­ º¼ ¼ö ÀÖ½À´Ï´Ù. === Skeleton Source (getopts version) === [http://www.cinsk.org/cgi-bin/viewcvs.cgi/snippets/filter-skel.sh ÃֽŠÄÚµå º¸±â] {{{#!vim sh #!/bin/sh # -*-sh-mode-*- # $Id: DevelFilterBashSkeleton,v 1.3 2005/07/13 04:41:16 kss Exp kss $ PATH=/usr/local/bin:/usr/bin:/bin program_name='skel' version_string='0.1' output_filename= verbose_mode=1 function error () { # usage: error EXIT_STATUS MESSAGE... # Print MESSAGE to the standard error (stderr) and call `exit EXIT_STATUS' # if EXIT-STATUS is nonzero. status="$1" shift; test -n "$program_name" && echo -n "$program_name: " echo "$@" test 0 -ne "$status" && exit "$status"; } 1>&2 function help_and_exit() { cat < EOF exit 0 } function version_and_exit() { cat <&2 function help_and_exit() { cat < EOF exit 0 } function version_and_exit() { cat <