1 <?xml version="1.0"?> 2 <?xml-stylesheet type="text/xsl" href="styleguide.xsl"?> 3 <GUIDE title="Shell Style Guide"> 4 5 <p align="right"> 6 7 Revision 1.26 8 </p> 9 10 11 <address> 12 Paul Armstrong<br/> 13 Too many more to mention<br/> 14 </address> 15 16 <OVERVIEW> 17 18 <CATEGORY title="Background"> 19 20 21 22 <STYLEPOINT title="Which Shell to Use"> 23 <SUMMARY> 24 <code>Bash</code> is the only shell scripting language permitted for 25 executables. 26 </SUMMARY> 27 <BODY> 28 <p> 29 Executables must start with <code>#!/bin/bash</code> and a minimum 30 number of flags. Use <code>set</code> to set shell options so that 31 calling your script as <code>bash <i><script_name></i></code> 32 does not break its functionality. 33 </p> 34 <p> 35 Restricting all executable shell scripts to <b>bash</b> 36 gives us a consistent shell language that's installed on all our 37 machines. 38 </p> 39 <p> 40 The only exception to this is where you're forced to by whatever 41 you're coding for. One example of this is Solaris SVR4 packages which 42 require plain Bourne shell for any scripts. 43 </p> 44 </BODY> 45 </STYLEPOINT> 46 47 <STYLEPOINT title="When to use Shell"> 48 <SUMMARY> 49 Shell should only be used for small utilities or simple wrapper 50 scripts. 51 </SUMMARY> 52 <BODY> 53 <p> 54 While shell scripting isn't a development language, it is used for 55 writing various utility scripts throughout Google. This 56 style guide is more a recognition of its use rather than 57 a suggestion that it be used for widespread deployment. 58 </p> 59 <p> 60 Some guidelines: 61 <ul> 62 <li> 63 If you're mostly calling other utilities and are doing relatively 64 little data manipulation, shell is an acceptable choice for the 65 task. 66 </li> 67 <li> 68 If performance matters, use something other than shell. 69 </li> 70 <li> 71 If you find you need to use arrays for anything more than 72 assignment of <code>${PIPESTATUS}</code>, you should use Python. 73 </li> 74 <li> 75 If you are writing a script that is more than 100 lines long, you 76 should probably be writing it in Python instead. Bear in mind 77 that scripts grow. Rewrite your script in another language 78 early to avoid a time-consuming rewrite at a later date. 79 </li> 80 </ul> 81 </p> 82 </BODY> 83 </STYLEPOINT> 84 </CATEGORY> 85 86 </OVERVIEW> 87 88 <CATEGORY title="Shell Files and Interpreter Invocation"> 89 90 <STYLEPOINT title="File Extensions"> 91 <SUMMARY> 92 Executables should have no extension (strongly preferred) or a 93 <code>.sh</code> extension. 94 Libraries must have a <code>.sh</code> extension and should not be 95 executable. 96 </SUMMARY> 97 <BODY> 98 <p> 99 It is not necessary to know what language a program is written in when 100 executing it and shell doesn't require an extension so we prefer not to 101 use one for executables. 102 </p> 103 <p> 104 However, for libraries it's important to know what language it is and 105 sometimes there's a need to have similar libraries in different 106 languages. This allows library files with identical purposes but 107 different languages to be identically named except for the 108 language-specific suffix. 109 </p> 110 </BODY> 111 </STYLEPOINT> 112 113 <STYLEPOINT title="SUID/SGID"> 114 <SUMMARY> 115 SUID and SGID are <em>forbidden</em> on shell scripts. 116 </SUMMARY> 117 <BODY> 118 <p> 119 There are too many security issues with shell that make it nearly 120 impossible to secure sufficiently to allow SUID/SGID. While bash does 121 make it difficult to run SUID, it's still possible on some platforms 122 which is why we're being explicit about banning it. 123 </p> 124 <p> 125 Use <code>sudo</code> to provide elevated access if you need it. 126 </p> 127 </BODY> 128 </STYLEPOINT> 129 130 </CATEGORY> 131 132 <CATEGORY title="Environment"> 133 134 <STYLEPOINT title="STDOUT vs STDERR"> 135 <SUMMARY> 136 All error messages should go to <code>STDERR</code>. 137 </SUMMARY> 138 <BODY> 139 <p> 140 This makes it easier 141 to separate normal status from actual issues. 142 </p> 143 <p> 144 A function to print out error messages along with other status 145 information is recommended. 146 <CODE_SNIPPET> 147 err() { 148 echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $@" >&2 149 } 150 151 if ! do_something; then 152 err "Unable to do_something" 153 exit "${E_DID_NOTHING}" 154 fi 155 </CODE_SNIPPET> 156 </p> 157 </BODY> 158 </STYLEPOINT> 159 160 </CATEGORY> 161 162 <CATEGORY title="Comments"> 163 164 <STYLEPOINT title="File Header"> 165 <SUMMARY> 166 Start each file with a description of its contents. 167 </SUMMARY> 168 <BODY> 169 <p> 170 Every file must have a top-level comment including a brief overview of 171 its contents. 172 A 173 copyright notice 174 and author information are optional. 175 </p> 176 <p> 177 Example: 178 <CODE_SNIPPET> 179 #!/bin/bash 180 # 181 # Perform hot backups of Oracle databases. 182 </CODE_SNIPPET> 183 </p> 184 185 186 </BODY> 187 </STYLEPOINT> 188 189 <STYLEPOINT title="Function Comments"> 190 <SUMMARY> 191 Any function that is not both obvious and short must be commented. Any 192 function in a library must be commented regardless of length or 193 complexity. 194 </SUMMARY> 195 <BODY> 196 <p> 197 It should be possible for someone else to learn how to use your 198 program or to use a function in your library by reading the comments 199 (and self-help, if provided) without reading the code. 200 </p> 201 <p> 202 All function comments should contain: 203 <ul> 204 <li> 205 Description of the function 206 </li> 207 <li> 208 Global variables used and modified 209 </li> 210 <li> 211 Arguments taken 212 </li> 213 <li> 214 Returned values other than the default exit status of the last 215 command run 216 </li> 217 </ul> 218 </p> 219 <p> 220 Example: 221 <CODE_SNIPPET> 222 #!/bin/bash 223 # 224 # Perform hot backups of Oracle databases. 225 226 export PATH='/usr/xpg4/bin:/usr/bin:/opt/csw/bin:/opt/goog/bin' 227 228 ####################################### 229 # Cleanup files from the backup dir 230 # Globals: 231 # BACKUP_DIR 232 # ORACLE_SID 233 # Arguments: 234 # None 235 # Returns: 236 # None 237 ####################################### 238 cleanup() { 239 ... 240 } 241 </CODE_SNIPPET> 242 </p> 243 </BODY> 244 </STYLEPOINT> 245 246 <STYLEPOINT title="Implementation Comments"> 247 <SUMMARY> 248 Comment tricky, non-obvious, interesting or important parts of your code. 249 </SUMMARY> 250 <BODY> 251 <p> 252 This follows general Google coding comment practice. Don't comment 253 everything. If there's a complex algorithm or you're doing something 254 out of the ordinary, put a short comment in. 255 </p> 256 </BODY> 257 </STYLEPOINT> 258 259 <STYLEPOINT title="TODO Comments"> 260 <SUMMARY> 261 Use TODO comments for code that is temporary, a short-term solution, or 262 good-enough but not perfect. 263 </SUMMARY> 264 <BODY> 265 <p> 266 This matches the convention in the <a href="cppguide.html?showone=TODO_Comments#TODO_Comments">C++ 267 Guide</a>. 268 </p> 269 <p> 270 TODOs should include the string TODO in all caps, followed by your 271 username in parentheses. A colon is optional. It's preferable to put a 272 bug/ticket number next to the TODO item as well. 273 </p> 274 <p> 275 Examples: 276 277 <CODE_SNIPPET> 278 # TODO(mrmonkey): Handle the unlikely edge cases (bug ####) 279 </CODE_SNIPPET> 280 </p> 281 </BODY> 282 </STYLEPOINT> 283 284 </CATEGORY> 285 286 <CATEGORY title="Formatting"> 287 <p> 288 While you should follow the style that's already there for files that 289 you're modifying, the following are required for any new code. 290 </p> 291 292 <STYLEPOINT title="Indentation"> 293 <SUMMARY> 294 Indent 2 spaces. No tabs. 295 </SUMMARY> 296 <BODY> 297 <p> 298 Use blank lines between blocks to improve readability. Indentation is 299 two spaces. Whatever you do, don't use tabs. For existing files, stay 300 faithful to the existing indentation. 301 </p> 302 </BODY> 303 </STYLEPOINT> 304 305 <STYLEPOINT title="Line Length and Long Strings"> 306 <SUMMARY> 307 Maximum line length is 80 characters. 308 </SUMMARY> 309 <BODY> 310 <p> 311 If you have to write strings that are longer than 80 characters, this 312 should be done with a here document or an embedded newline if possible. 313 Literal strings that have to be longer than 80 chars and can't sensibly 314 be split are ok, but it's strongly preferred to find a way to make it 315 shorter. 316 </p> 317 <p> 318 <CODE_SNIPPET> 319 # DO use 'here document's 320 cat <<END; 321 I am an exceptionally long 322 string. 323 END 324 325 # Embedded newlines are ok too 326 long_string="I am an exceptionally 327 long string." 328 </CODE_SNIPPET> 329 </p> 330 </BODY> 331 </STYLEPOINT> 332 333 <STYLEPOINT title="Pipelines"> 334 <SUMMARY> 335 Pipelines should be split one per line if they don't all fit on one line. 336 </SUMMARY> 337 <BODY> 338 <p> 339 If a pipeline all fits on one line, it should be on one line. 340 </p> 341 <p> 342 If not, it should be split at one pipe segment per line with the pipe 343 on the newline and a 2 space indent for the next section of the pipe. 344 This applies to a chain of commands combined using '|' as well as to 345 logical compounds using '||' and '&&'. 346 <CODE_SNIPPET> 347 # All fits on one line 348 command1 | command2 349 350 # Long commands 351 command1 \ 352 | command2 \ 353 | command3 \ 354 | command4 355 </CODE_SNIPPET> 356 </p> 357 </BODY> 358 </STYLEPOINT> 359 360 <STYLEPOINT title="Loops"> 361 <SUMMARY> 362 Put <code>; do</code> and <code>; then</code> on the same line as the 363 <code>while</code>, <code>for</code> or <code>if</code>. 364 </SUMMARY> 365 <BODY> 366 <p> 367 Loops in shell are a bit different, but we follow the same principles 368 as with braces when declaring functions. That is: <code>; then</code> 369 and <code>; do</code> should be on the same line as the if/for/while. 370 <code>else</code> should be on its own line and closing statements 371 should be on their own line vertically aligned with the opening 372 statement. 373 </p> 374 <p> 375 Example: 376 <CODE_SNIPPET> 377 for dir in ${dirs_to_cleanup}; do 378 if [[ -d "${dir}/${ORACLE_SID}" ]]; then 379 log_date "Cleaning up old files in ${dir}/${ORACLE_SID}" 380 rm "${dir}/${ORACLE_SID}/"* 381 if [[ "$?" -ne 0 ]]; then 382 error_message 383 fi 384 else 385 mkdir -p "${dir}/${ORACLE_SID}" 386 if [[ "$?" -ne 0 ]]; then 387 error_message 388 fi 389 fi 390 done 391 </CODE_SNIPPET> 392 </p> 393 </BODY> 394 </STYLEPOINT> 395 396 <STYLEPOINT title="Case statement"> 397 <SUMMARY> 398 <ul> 399 <li> 400 Indent alternatives by 2 spaces. 401 </li> 402 <li> 403 A one-line alternative needs a space after the close parenthesis of 404 the pattern and before the <code>;;</code>. 405 </li> 406 <li> 407 Long or multi-command alternatives should be split over multiple 408 lines with the pattern, actions, and <code>;;</code> on separate 409 lines. 410 </li> 411 </ul> 412 </SUMMARY> 413 <BODY> 414 <p> 415 The matching expressions are indented one level from the 'case' and 416 'esac'. Multiline actions are indented another level. In general, 417 there is no need to quote match expressions. Pattern expressions 418 should not be preceded by an open parenthesis. Avoid the 419 <code>;&</code> and <code>;;&</code> notations. 420 </p> 421 <CODE_SNIPPET> 422 case "${expression}" in 423 a) 424 variable="..." 425 some_command "${variable}" "${other_expr}" ... 426 ;; 427 absolute) 428 actions="relative" 429 another_command "${actions}" "${other_expr}" ... 430 ;; 431 *) 432 error "Unexpected expression '${expression}'" 433 ;; 434 esac 435 </CODE_SNIPPET> 436 <p> 437 Simple commands may be put on the same line as the pattern <i>and</i> 438 <code>;;</code> as long as the expression remains readable. This is 439 often appropriate for single-letter option processing. When the 440 actions don't fit on a single line, put the pattern on a line on its 441 own, then the actions, then <code>;;</code> also on a line of its own. 442 When on the same line as the actions, use a space after the close 443 parenthesis of the pattern and another before the <code>;;</code>. 444 </p> 445 <CODE_SNIPPET> 446 verbose='false' 447 aflag='' 448 bflag='' 449 files='' 450 while getopts 'abf:v' flag; do 451 case "${flag}" in 452 a) aflag='true' ;; 453 b) bflag='true' ;; 454 f) files="${OPTARG}" ;; 455 v) verbose='true' ;; 456 *) error "Unexpected option ${flag}" ;; 457 esac 458 done 459 </CODE_SNIPPET> 460 </BODY> 461 </STYLEPOINT> 462 463 <STYLEPOINT title="Variable expansion"> 464 <SUMMARY> 465 In order of precedence: Stay consistent with what you find; 466 quote your variables; 467 prefer "${var}" over "$var", but see details. 468 </SUMMARY> 469 <BODY> 470 <p> 471 These are meant to be guidelines, as the topic seems too controversial for 472 a mandatory regulation. 473 <br/> 474 They are listed in order of precedence. 475 </p> 476 <ol> 477 <li> 478 Stay consistent with what you find for existing code. 479 </li> 480 <li> 481 Quote variables, see <a href="#Quoting">Quoting section below</a>. 482 </li> 483 <li> 484 <p> 485 Don't brace-quote single character shell 486 specials / positional parameters, unless strictly necessary 487 or avoiding deep confusion. 488 <br/> 489 Prefer brace-quoting all other variables. 490 <CODE_SNIPPET> 491 # Section of <em>recommended</em> cases. 492 493 # Preferred style for 'special' variables: 494 echo "Positional: $1" "$5" "$3" 495 echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ ..." 496 497 # Braces necessary: 498 echo "many parameters: ${10}" 499 500 # Braces avoiding confusion: 501 # Output is "a0b0c0" 502 set -- a b c 503 echo "${1}0${2}0${3}0" 504 505 # Preferred style for other variables: 506 echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}" 507 while read f; do 508 echo "file=${f}" 509 done < <(ls -l /tmp) 510 511 # Section of <em>discouraged</em> cases 512 513 # Unquoted vars, unbraced vars, brace-quoted single letter 514 # shell specials. 515 echo a=$avar "b=$bvar" "PID=${$}" "${1}" 516 517 # Confusing use: this is expanded as "${1}0${2}0${3}0", 518 # not "${10}${20}${30} 519 set -- a b c 520 echo "$10$20$30" 521 </CODE_SNIPPET> 522 </p> 523 </li> 524 </ol> 525 </BODY> 526 </STYLEPOINT> 527 528 <STYLEPOINT title="Quoting"> 529 <SUMMARY> 530 <ul> 531 <li> 532 Always quote strings containing variables, command substitutions, 533 spaces or shell meta characters, unless careful unquoted expansion 534 is required. 535 </li> 536 <li> 537 Prefer quoting strings that are "words" 538 (as opposed to command options or path names). 539 </li> 540 <li> 541 Never quote <em>literal</em> integers. 542 </li> 543 <li> 544 Be aware of the quoting rules for 545 <a href="#Test,_%5B_and_%5B%5B">pattern matches in [[</a>. 546 </li> 547 <li> 548 Use "$@" unless you have a specific reason to use $*. 549 </li> 550 </ul> 551 </SUMMARY> 552 <BODY> 553 <p> 554 <CODE_SNIPPET> 555 # 'Single' quotes indicate that no substitution is desired. 556 # "Double" quotes indicate that substitution is required/tolerated. 557 558 # Simple examples 559 # "quote command substitutions" 560 flag="$(some_command and its args "$@" 'quoted separately')" 561 562 # "quote variables" 563 echo "${flag}" 564 565 # "never quote literal integers" 566 value=32 567 # "quote command substitutions", even when you expect integers 568 number="$(generate_number)" 569 570 # "prefer quoting words", not compulsory 571 readonly USE_INTEGER='true' 572 573 # "quote shell meta characters" 574 echo 'Hello stranger, and well met. Earn lots of $$$' 575 echo "Process $$: Done making \$\$\$." 576 577 # "command options or path names" 578 # ($1 is assumed to contain a value here) 579 grep -li Hugo /dev/null "$1" 580 581 # Less simple examples 582 # "quote variables, unless proven false": ccs might be empty 583 git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"} 584 585 # Positional parameter precautions: $1 might be unset 586 # Single quotes leave regex as-is. 587 grep -cP '([Ss]pecial|\|?characters*)$' ${1:+"$1"} 588 589 # For passing on arguments, 590 # "$@" is right almost everytime, and 591 # $* is wrong almost everytime: 592 # 593 # * $* and $@ will split on spaces, clobbering up arguments 594 # that contain spaces and dropping empty strings; 595 # * "$@" will retain arguments as-is, so no args 596 # provided will result in no args being passed on; 597 # This is in most cases what you want to use for passing 598 # on arguments. 599 # * "$*" expands to one argument, with all args joined 600 # by (usually) spaces, 601 # so no args provided will result in one empty string 602 # being passed on. 603 # (Consult 'man bash' for the nit-grits ;-) 604 605 set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$*"; echo "$#, $@") 606 set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$@"; echo "$#, $@") 607 </CODE_SNIPPET> 608 </p> 609 </BODY> 610 </STYLEPOINT> 611 612 </CATEGORY> 613 614 <CATEGORY title="Features and Bugs"> 615 616 <STYLEPOINT title="Command Substitution"> 617 <SUMMARY> 618 Use <code>$(command)</code> instead of backticks. 619 </SUMMARY> 620 <BODY> 621 <p> 622 Nested backticks require escaping the inner ones with <code>\</code>. 623 The <code>$(command)</code> format doesn't change when nested and is 624 easier to read. 625 </p> 626 <p> 627 Example: 628 <CODE_SNIPPET> 629 # This is preferred: 630 var="$(command "$(command1)")" 631 632 # This is not: 633 var="`command \`command1\``" 634 </CODE_SNIPPET> 635 </p> 636 </BODY> 637 </STYLEPOINT> 638 639 <STYLEPOINT title="Test, [ and [["> 640 <SUMMARY> 641 <code>[[ ... ]]</code> is preferred over <code>[</code>, 642 <code>test</code> and <code>/usr/bin/[</code>. 643 </SUMMARY> 644 <BODY> 645 <p> 646 <code>[[ ... ]]</code> reduces errors as no pathname expansion or word 647 splitting takes place between <code>[[</code> and <code>]]</code> and 648 <code>[[ ... ]]</code> allows for regular expression matching where 649 <code>[ ... ]</code> does not. 650 <CODE_SNIPPET> 651 # This ensures the string on the left is made up of characters in the 652 # alnum character class followed by the string name. 653 # Note that the RHS should not be quoted here. 654 # For the gory details, see 655 # E14 at https://tiswww.case.edu/php/chet/bash/FAQ 656 if [[ "filename" =~ ^[[:alnum:]]+name ]]; then 657 echo "Match" 658 fi 659 660 # This matches the exact pattern "f*" (Does not match in this case) 661 if [[ "filename" == "f*" ]]; then 662 echo "Match" 663 fi 664 665 # This gives a "too many arguments" error as f* is expanded to the 666 # contents of the current directory 667 if [ "filename" == f* ]; then 668 echo "Match" 669 fi 670 </CODE_SNIPPET> 671 </p> 672 </BODY> 673 </STYLEPOINT> 674 675 <STYLEPOINT title="Testing Strings"> 676 <SUMMARY> 677 Use quotes rather than filler characters where possible. 678 </SUMMARY> 679 <BODY> 680 <p> 681 Bash is smart enough to deal with an empty string in a test. So, given 682 that the code is much easier to read, use tests for empty/non-empty 683 strings or empty strings rather than filler characters. 684 <CODE_SNIPPET> 685 # Do this: 686 if [[ "${my_var}" = "some_string" ]]; then 687 do_something 688 fi 689 690 # -z (string length is zero) and -n (string length is not zero) are 691 # preferred over testing for an empty string 692 if [[ -z "${my_var}" ]]; then 693 do_something 694 fi 695 696 # This is OK (ensure quotes on the empty side), but not preferred: 697 if [[ "${my_var}" = "" ]]; then 698 do_something 699 fi 700 701 # Not this: 702 if [[ "${my_var}X" = "some_stringX" ]]; then 703 do_something 704 fi 705 </CODE_SNIPPET> 706 </p> 707 <p> 708 To avoid confusion about what you're testing for, explicitly use 709 <code>-z</code> or <code>-n</code>. 710 <CODE_SNIPPET> 711 # Use this 712 if [[ -n "${my_var}" ]]; then 713 do_something 714 fi 715 716 # Instead of this as errors can occur if ${my_var} expands to a test 717 # flag 718 if [[ "${my_var}" ]]; then 719 do_something 720 fi 721 </CODE_SNIPPET> 722 </p> 723 </BODY> 724 </STYLEPOINT> 725 726 <STYLEPOINT title="Wildcard Expansion of Filenames"> 727 <SUMMARY> 728 Use an explicit path when doing wildcard expansion of filenames. 729 </SUMMARY> 730 <BODY> 731 <p> 732 As filenames can begin with a <code>-</code>, it's a lot safer to 733 expand wildcards with <code>./*</code> instead of <code>*</code>. 734 <CODE_SNIPPET> 735 # Here's the contents of the directory: 736 # -f -r somedir somefile 737 738 # This deletes almost everything in the directory by force 739 psa@bilby$ rm -v * 740 removed directory: `somedir' 741 removed `somefile' 742 743 # As opposed to: 744 psa@bilby$ rm -v ./* 745 removed `./-f' 746 removed `./-r' 747 rm: cannot remove `./somedir': Is a directory 748 removed `./somefile' 749 </CODE_SNIPPET> 750 </p> 751 </BODY> 752 </STYLEPOINT> 753 754 <STYLEPOINT title="Eval"> 755 <SUMMARY> 756 <code>eval</code> should be avoided. 757 </SUMMARY> 758 <BODY> 759 <p> 760 Eval munges the input when used for assignment to variables and can set 761 variables without making it possible to check what those variables 762 were. 763 <CODE_SNIPPET> 764 # What does this set? 765 # Did it succeed? In part or whole? 766 eval $(set_my_variables) 767 768 # What happens if one of the returned values has a space in it? 769 variable="$(eval some_function)" 770 </CODE_SNIPPET> 771 </p> 772 </BODY> 773 </STYLEPOINT> 774 775 <STYLEPOINT title="Pipes to While"> 776 <SUMMARY> 777 Use process substitution or for loops in preference to piping to while. 778 Variables modified in a while loop do not propagate to the parent 779 because the loop's commands run in a subshell. 780 </SUMMARY> 781 <BODY> 782 <p> 783 The implicit subshell in a pipe to while can make it difficult to track 784 down bugs. 785 <BAD_CODE_SNIPPET> 786 last_line='NULL' 787 your_command | while read line; do 788 last_line="${line}" 789 done 790 791 # This will output 'NULL' 792 echo "${last_line}" 793 </BAD_CODE_SNIPPET> 794 </p> 795 <p> 796 Use a for loop if you are confident that the input will not contain 797 spaces or special characters (usually, this means not user input). 798 <CODE_SNIPPET> 799 total=0 800 # Only do this if there are no spaces in return values. 801 for value in $(command); do 802 total+="${value}" 803 done 804 </CODE_SNIPPET> 805 </p> 806 <p> 807 Using process substitution allows redirecting output but puts the 808 commands in an explicit subshell rather than the implicit subshell that 809 bash creates for the while loop. 810 <CODE_SNIPPET> 811 total=0 812 last_file= 813 while read count filename; do 814 total+="${count}" 815 last_file="${filename}" 816 done < <(your_command | uniq -c) 817 818 # This will output the second field of the last line of output from 819 # the command. 820 echo "Total = ${total}" 821 echo "Last one = ${last_file}" 822 </CODE_SNIPPET> 823 </p> 824 <p> 825 Use while loops where it is not necessary to pass complex results 826 to the parent shell - this is typically where some more complex 827 "parsing" is required. Beware that simple examples are probably 828 more easily done with a tool such as awk. This may also be useful 829 where you specifically don't want to change the parent scope variables. 830 <CODE_SNIPPET> 831 # Trivial implementation of awk expression: 832 # awk '$3 == "nfs" { print $2 " maps to " $1 }' /proc/mounts 833 cat /proc/mounts | while read src dest type opts rest; do 834 if [[ ${type} == "nfs" ]]; then 835 echo "NFS ${dest} maps to ${src}" 836 fi 837 done 838 </CODE_SNIPPET> 839 </p> 840 </BODY> 841 </STYLEPOINT> 842 843 </CATEGORY> 844 845 <CATEGORY title="Naming Conventions"> 846 847 <STYLEPOINT title="Function Names"> 848 <SUMMARY> 849 Lower-case, with underscores to separate words. Separate libraries 850 with <code>::</code>. Parentheses are required after the function name. 851 The keyword <code>function</code> is optional, but must be used 852 consistently throughout a project. 853 </SUMMARY> 854 <BODY> 855 <p> 856 If you're writing single functions, use lowercase and separate words 857 with underscore. If you're writing a package, separate package names 858 with <code>::</code>. Braces must be on the same line as the function 859 name (as with other languages at Google) and no space between the 860 function name and the parenthesis. 861 <CODE_SNIPPET> 862 # Single function 863 my_func() { 864 ... 865 } 866 867 # Part of a package 868 mypackage::my_func() { 869 ... 870 } 871 </CODE_SNIPPET> 872 </p> 873 <p> 874 The <code>function</code> keyword is extraneous when "()" is present 875 after the function name, but enhances quick identification of 876 functions. 877 </p> 878 </BODY> 879 </STYLEPOINT> 880 881 <STYLEPOINT title="Variable Names"> 882 <SUMMARY> 883 As for function names. 884 </SUMMARY> 885 <BODY> 886 <p> 887 Variables names for loops should be similarly named for any variable 888 you're looping through. 889 <CODE_SNIPPET> 890 for zone in ${zones}; do 891 something_with "${zone}" 892 done 893 </CODE_SNIPPET> 894 </p> 895 </BODY> 896 </STYLEPOINT> 897 898 <STYLEPOINT title="Constants and Environment Variable Names"> 899 <SUMMARY> 900 All caps, separated with underscores, declared at the top of the file. 901 </SUMMARY> 902 <BODY> 903 <p> 904 Constants and anything exported to the environment should be 905 capitalized. 906 <CODE_SNIPPET> 907 # Constant 908 readonly PATH_TO_FILES='/some/path' 909 910 # Both constant and environment 911 declare -xr ORACLE_SID='PROD' 912 </CODE_SNIPPET> 913 </p> 914 <p> 915 Some things become constant at their first setting (for example, via 916 getopts). Thus, it's OK to set a constant in getopts or based on a 917 condition, but it should be made readonly immediately afterwards. 918 Note that <code>declare</code> doesn't operate on global variables 919 within functions, so <code>readonly</code> or <code>export</code> is 920 recommended instead. 921 </p> 922 <CODE_SNIPPET> 923 VERBOSE='false' 924 while getopts 'v' flag; do 925 case "${flag}" in 926 v) VERBOSE='true' ;; 927 esac 928 done 929 readonly VERBOSE 930 </CODE_SNIPPET> 931 </BODY> 932 </STYLEPOINT> 933 934 <STYLEPOINT title="Source Filenames"> 935 <SUMMARY> 936 Lowercase, with underscores to separate words if desired. 937 </SUMMARY> 938 <BODY> 939 <p> 940 This is for consistency with other code styles in Google: 941 <code>maketemplate</code> or <code>make_template</code> but not 942 <code>make-template</code>. 943 </p> 944 </BODY> 945 </STYLEPOINT> 946 947 <STYLEPOINT title="Read-only Variables"> 948 <SUMMARY> 949 Use <code>readonly</code> or <code>declare -r</code> to ensure they're 950 read only. 951 </SUMMARY> 952 <BODY> 953 <p> 954 As globals are widely used in shell, it's important to catch errors 955 when working with them. When you declare a variable that is 956 meant to be read-only, make this explicit. 957 <CODE_SNIPPET> 958 zip_version="$(dpkg --status zip | grep Version: | cut -d ' ' -f 2)" 959 if [[ -z "${zip_version}" ]]; then 960 error_message 961 else 962 readonly zip_version 963 fi 964 </CODE_SNIPPET> 965 </p> 966 </BODY> 967 </STYLEPOINT> 968 969 <STYLEPOINT title="Use Local Variables"> 970 <SUMMARY> 971 Declare function-specific variables with <code>local</code>. Declaration 972 and assignment should be on different lines. 973 </SUMMARY> 974 <BODY> 975 <p> 976 Ensure that local variables are only seen inside a function and its 977 children by using <code>local</code> when declaring them. This avoids 978 polluting the global name space and inadvertently setting variables 979 that may have significance outside the function. 980 </p> 981 <p> 982 Declaration and assignment must be separate statements when 983 the assignment value is provided by a command substitution; as 984 the 'local' builtin does not propagate the exit code from the 985 command substitution. 986 <CODE_SNIPPET> 987 my_func2() { 988 local name="$1" 989 990 # Separate lines for declaration and assignment: 991 local my_var 992 my_var="$(my_func)" || return 993 994 # DO NOT do this: $? contains the exit code of 'local', not my_func 995 local my_var="$(my_func)" 996 [[ $? -eq 0 ]] || return 997 998 ... 999 } 1000 </CODE_SNIPPET> 1001 </p> 1002 </BODY> 1003 </STYLEPOINT> 1004 1005 <STYLEPOINT title="Function Location"> 1006 <SUMMARY> 1007 Put all functions together in the file just below constants. Don't hide 1008 executable code between functions. 1009 </SUMMARY> 1010 <BODY> 1011 <p> 1012 If you've got functions, put them all together near the top of the 1013 file. Only includes, <code>set</code> statements and setting constants 1014 may be done before declaring functions. 1015 </p> 1016 <p> 1017 Don't hide executable code between functions. Doing so makes the code 1018 difficult to follow and results in nasty surprises when debugging. 1019 </p> 1020 </BODY> 1021 </STYLEPOINT> 1022 1023 <STYLEPOINT title="main"> 1024 <SUMMARY> 1025 A function called <code>main</code> is required for scripts long enough 1026 to contain at least one other function. 1027 </SUMMARY> 1028 <BODY> 1029 <p> 1030 In order to easily find the start of the program, put the main 1031 program in a function called <code>main</code> as the bottom most 1032 function. This provides consistency with the rest of the code base as 1033 well as allowing you to define more variables as <code>local</code> 1034 (which can't be done if the main code is not a function). The last 1035 non-comment line in the file should be a call to <code>main</code>: 1036 <CODE_SNIPPET> 1037 main "$@" 1038 </CODE_SNIPPET> 1039 </p> 1040 <p> 1041 Obviously, for short scripts where it's just a linear flow, 1042 <code>main</code> is overkill and so is not required. 1043 </p> 1044 </BODY> 1045 </STYLEPOINT> 1046 1047 </CATEGORY> 1048 1049 <CATEGORY title="Calling Commands"> 1050 1051 <STYLEPOINT title="Checking Return Values"> 1052 <SUMMARY> 1053 Always check return values and give informative return values. 1054 </SUMMARY> 1055 <BODY> 1056 <p> 1057 For unpiped commands, use <code>$?</code> or check directly via an 1058 <code>if</code> statement to keep it simple. 1059 </p> 1060 <p> 1061 Example: 1062 <CODE_SNIPPET> 1063 if ! mv "${file_list}" "${dest_dir}/" ; then 1064 echo "Unable to move ${file_list} to ${dest_dir}" >&2 1065 exit "${E_BAD_MOVE}" 1066 fi 1067 1068 # Or 1069 mv "${file_list}" "${dest_dir}/" 1070 if [[ "$?" -ne 0 ]]; then 1071 echo "Unable to move ${file_list} to ${dest_dir}" >&2 1072 exit "${E_BAD_MOVE}" 1073 fi 1074 1075 </CODE_SNIPPET> 1076 </p> 1077 <p> 1078 Bash also has the <code>PIPESTATUS</code> variable that allows checking 1079 of the return code from all parts of a pipe. If it's only necessary to 1080 check success or failure of the whole pipe, then the following is 1081 acceptable: 1082 <CODE_SNIPPET> 1083 tar -cf - ./* | ( cd "${dir}" && tar -xf - ) 1084 if [[ "${PIPESTATUS[0]}" -ne 0 || "${PIPESTATUS[1]}" -ne 0 ]]; then 1085 echo "Unable to tar files to ${dir}" >&2 1086 fi 1087 </CODE_SNIPPET> 1088 </p> 1089 <p> 1090 However, as <code>PIPESTATUS</code> will be overwritten as soon as you 1091 do any other command, if you need to act differently on errors based on 1092 where it happened in the pipe, you'll need to assign 1093 <code>PIPESTATUS</code> to another variable immediately after running 1094 the command (don't forget that <code>[</code> is a command and will 1095 wipe out <code>PIPESTATUS</code>). 1096 <CODE_SNIPPET> 1097 tar -cf - ./* | ( cd "${DIR}" && tar -xf - ) 1098 return_codes=(${PIPESTATUS[*]}) 1099 if [[ "${return_codes[0]}" -ne 0 ]]; then 1100 do_something 1101 fi 1102 if [[ "${return_codes[1]}" -ne 0 ]]; then 1103 do_something_else 1104 fi 1105 </CODE_SNIPPET> 1106 </p> 1107 </BODY> 1108 </STYLEPOINT> 1109 1110 <STYLEPOINT title="Builtin Commands vs. External Commands"> 1111 <SUMMARY> 1112 Given the choice between invoking a shell builtin and invoking a separate 1113 process, choose the builtin. 1114 </SUMMARY> 1115 <BODY> 1116 <p> 1117 We prefer the use of builtins such as the <em>Parameter Expansion</em> 1118 functions in <code>bash(1)</code> as it's more robust and portable 1119 (especially when compared to things like sed). 1120 </p> 1121 <p> 1122 Example: 1123 <CODE_SNIPPET> 1124 # Prefer this: 1125 addition=$((${X} + ${Y})) 1126 substitution="${string/#foo/bar}" 1127 1128 # Instead of this: 1129 addition="$(expr ${X} + ${Y})" 1130 substitution="$(echo "${string}" | sed -e 's/^foo/bar/')" 1131 </CODE_SNIPPET> 1132 </p> 1133 </BODY> 1134 </STYLEPOINT> 1135 1136 </CATEGORY> 1137 1138 <CATEGORY title="Conclusion"> 1139 <p> 1140 Use common sense and <em>BE CONSISTENT</em>. 1141 </p> 1142 <p> 1143 Please take a few minutes to read the Parting Words section at the bottom 1144 of the <a href="cppguide.html">C++ Guide</a>. 1145 </p> 1146 </CATEGORY> 1147 1148 <p align="right"> 1149 Revision 1.26 1150 </p> 1151 1152 </GUIDE> 1153