bash-hackers-wiki/commands/classictest/index.html

237 lines
103 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href=https://flokoe.github.io/bash-hackers-wiki/commands/classictest/ rel=canonical><link rel=prev href=../..><link href=../builtin/caller/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.44"><title>The classic test command - The Bash Hackers Wiki</title><link rel=stylesheet href=../../assets/stylesheets/main.0253249f.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.06af60db.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#the-classic-test-command class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../.. title="The Bash Hackers Wiki" class="md-header__button md-logo" aria-label="The Bash Hackers Wiki" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> The Bash Hackers Wiki </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> The classic test command </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media data-md-color-scheme=slate data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input name=query aria-label=Search placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=search-query required> <label class="md-search__icon md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </label> <nav class=md-search__options aria-label=Search> <button type=reset class="md-search__icon md-icon" title=Clear aria-label=Clear tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> </button> </nav> <div class=md-search__suggest data-md-component=search-suggest></div> </form> <div class=md-search__output> <div class=md-search__scrollwrap tabindex=0 data-md-scrollfix> <div class=md-search-result data-md-component=search-result> <div class=md-search-result__meta> Initializing search </div> <ol class=md-search-result__list role=presentation></ol> </div> </div> </div> </div> </div> <div class=md-header__source> <a href=https://github.com/flokoe/bash-hackers-wiki title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> flokoe/bash-hackers-wiki </div> </a> </div> </nav> </header> <div class=md-container data-md-component=container> <nav class=md-tabs aria-label=Tabs data-md-component=tabs> <div class=md-grid> <ul class=md-tabs__list> <li class=md-tabs__item> <a href=../.. class=md-tabs__link> Start </a> </li> <li class="md-tabs__item md-tabs__item--active"> <a href=./ class=md-tabs__link> Commands </a> </li> <li class=md-tabs__item> <a href=../../dict/directory/ class=md-tabs__link> Dict </a> </li> <li class=md-tabs__item> <a href=../../howto/calculate-dc/ class=md-tabs__link> Howto </a> </li> <li class=md-tabs__item> <a href=../../internals/shell_options/ class=md-tabs__link> Internals </a> </li> <li class=md-tabs__item> <a href=../../misc/bashphorisms/ class=md-tabs__link> Misc </a> </li> <li class=md-tabs__item> <a href=../../scripting/bashbehaviour/ class=md-tabs__link> Scripting </a> </li> <li class=md-tabs__item> <a href=../../snipplets/ class=md-tabs__link> Snipplets </a> </li> <li class=md-tabs__item> <a href=../../syntax/arith_expr/ class=md-tabs__link> Syntax </a> </li> <li class=md-tabs__item> <a href=../../tags/ class=md-tabs__link> Tags </a> </li> </ul> </div> </nav> <main class=md-main data-md-component=main> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component=sidebar data-md-type=navigation> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--primary md-nav--lifted" aria-label=Navigation data-md-level=0> <label class=md-nav__title for=__drawer> <a href=../.. title="The Bash Hackers Wiki" class="md-nav__button md-logo" aria-label="The Bash Hackers Wiki" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> The Bash Hackers Wiki </label> <div class=md-nav__source> <a href=https://github.com/flokoe/bash-hackers-wiki title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> flokoe/bash-hackers-wiki </div> </a> </div> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../.. class=md-nav__link> <span class=md-ellipsis> Start </span> </a> </li> <li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_2 checked> <label class=md-nav__link for=__nav_2 id=__nav_2_label tabindex> <span class=md-ellipsis> Commands </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_2_label aria-expanded=true> <label class=md-nav__title for=__nav_2> <span class="md-nav__icon md-icon"></span> Commands </label> <ul class=md-nav__list data-md-scrollfix> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" type=checkbox id=__toc> <label class="md-nav__link md-nav__link--active" for=__toc> <span class=md-ellipsis> The classic test command </span> <span class="md-nav__icon md-icon"></span> </label> <a href=./ class="md-nav__link md-nav__link--active"> <span class=md-ellipsis> The classic test command </span> </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#general-syntax class=md-nav__link> <span class=md-ellipsis> General syntax </span> </a> </li> <li class=md-nav__item> <a href=#file-tests class=md-nav__link> <span class=md-ellipsis> File tests </span> </a> </li> <li class=md-nav__item> <a href=#string-tests class=md-nav__link> <span class=md-ellipsis> String tests </span> </a> </li> <li class=md-nav__item> <a href=#arithmetic-tests class=md-nav__link> <span class=md-ellipsis> Arithmetic tests </span> </a> </li> <li class=md-nav__item> <a href=#misc-syntax class=md-nav__link> <span class=md-ellipsis> Misc syntax </span> </a> </li> <li class=md-nav__item> <a href=#number-of-arguments-rules class=md-nav__link> <span class=md-ellipsis> Number of Arguments Rules </span> </a> </li> <li class=md-nav__item> <a href=#and-and-or class=md-nav__link> <span class=md-ellipsis> AND and OR </span> </a> <nav class=md-nav aria-label="AND and OR"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#the-prefered-way class=md-nav__link> <span class=md-ellipsis> The Prefered Way </span> </a> </li> <li class=md-nav__item> <a href=#the-other-way-a-and-o class=md-nav__link> <span class=md-ellipsis> The other way: -a and -o </span> </a> </li> <li class=md-nav__item> <a href=#why-you-should-avoid-using-a-and-o class=md-nav__link> <span class=md-ellipsis> Why you should avoid using -a and -o </span> </a> <nav class=md-nav aria-label="Why you should avoid using -a and -o"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#if-portability-is-a-concern class=md-nav__link> <span class=md-ellipsis> If portability is a concern </span> </a> </li> <li class=md-nav__item> <a href=#if-you-want-the-cut-behaviour class=md-nav__link> <span class=md-ellipsis> If you want the cut behaviour </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#precedence-and-parenthesis class=md-nav__link> <span class=md-ellipsis> Precedence and Parenthesis </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#not class=md-nav__link> <span class=md-ellipsis> NOT </span> </a> </li> <li class=md-nav__item> <a href=#pitfalls-summarized class=md-nav__link> <span class=md-ellipsis> Pitfalls summarized </span> </a> <nav class=md-nav aria-label="Pitfalls summarized"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#general class=md-nav__link> <span class=md-ellipsis> General </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#code-examples class=md-nav__link> <span class=md-ellipsis> Code examples </span> </a> <nav class=md-nav aria-label="Code examples"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#snipplets class=md-nav__link> <span class=md-ellipsis> Snipplets </span> </a> </li> <li class=md-nav__item> <a href=#listing-directories class=md-nav__link> <span class=md-ellipsis> Listing directories </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#see-also class=md-nav__link> <span class=md-ellipsis> See also </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_2_2> <label class=md-nav__link for=__nav_2_2 id=__nav_2_2_label tabindex> <span class=md-ellipsis> Builtin </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_2_2_label aria-expanded=false> <label class=md-nav__title for=__nav_2_2> <span class="md-nav__icon md-icon"></span> Builtin </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../builtin/caller/ class=md-nav__link> <span class=md-ellipsis> The caller builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/cd/ class=md-nav__link> <span class=md-ellipsis> The cd builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/declare/ class=md-nav__link> <span class=md-ellipsis> The declare builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/echo/ class=md-nav__link> <span class=md-ellipsis> The echo builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/eval/ class=md-nav__link> <span class=md-ellipsis> The eval builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/exec/ class=md-nav__link> <span class=md-ellipsis> The exec builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/exit/ class=md-nav__link> <span class=md-ellipsis> The exit builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/export/ class=md-nav__link> <span class=md-ellipsis> The export builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/kill/ class=md-nav__link> <span class=md-ellipsis> The kill builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/let/ class=md-nav__link> <span class=md-ellipsis> The let builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/local/ class=md-nav__link> <span class=md-ellipsis> The local builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/mapfile/ class=md-nav__link> <span class=md-ellipsis> The mapfile builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/printf/ class=md-nav__link> <span class=md-ellipsis> The printf command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/read/ class=md-nav__link> <span class=md-ellipsis> The read builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/readonly/ class=md-nav__link> <span class=md-ellipsis> The readonly builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/return/ class=md-nav__link> <span class=md-ellipsis> The return builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/set/ class=md-nav__link> <span class=md-ellipsis> The set builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/shift/ class=md-nav__link> <span class=md-ellipsis> The shift builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/shopt/ class=md-nav__link> <span class=md-ellipsis> The shopt builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/trap/ class=md-nav__link> <span class=md-ellipsis> The trap builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/unset/ class=md-nav__link> <span class=md-ellipsis> The unset builtin command </span> </a> </li> <li class=md-nav__item> <a href=../builtin/wait/ class=md-nav__link> <span class=md-ellipsis> The wait builtin command </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_3> <label class=md-nav__link for=__nav_3 id=__nav_3_label tabindex=0> <span class=md-ellipsis> Dict </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_3_label aria-expanded=false> <label class=md-nav__title for=__nav_3> <span class="md-nav__icon md-icon"></span> Dict </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../dict/directory/ class=md-nav__link> <span class=md-ellipsis> Directory </span> </a> </li> <li class=md-nav__item> <a href=../../dict/end_of_options/ class=md-nav__link> <span class=md-ellipsis> End of Options </span> </a> </li> <li class=md-nav__item> <a href=../../dict/exit_status/ class=md-nav__link> <span class=md-ellipsis> Exit Status </span> </a> </li> <li class=md-nav__item> <a href=../../dict/file/ class=md-nav__link> <span class=md-ellipsis> File </span> </a> </li> <li class=md-nav__item> <a href=../../dict/filetimes/ class=md-nav__link> <span class=md-ellipsis> File timestamp </span> </a> </li> <li class=md-nav__item> <a href=../../dict/globbing/ class=md-nav__link> <span class=md-ellipsis> Globbing </span> </a> </li> <li class=md-nav__item> <a href=../../dict/hardlink/ class=md-nav__link> <span class=md-ellipsis> Hardlink </span> </a> </li> <li class=md-nav__item> <a href=../../dict/interpreter_directive/ class=md-nav__link> <span class=md-ellipsis> Interpreter Directive </span> </a> </li> <li class=md-nav__item> <a href=../../dict/parameter/ class=md-nav__link> <span class=md-ellipsis> Parameter </span> </a> </li> <li class=md-nav__item> <a href=../../dict/posix/ class=md-nav__link> <span class=md-ellipsis> POSIX </span> </a> </li> <li class=md-nav__item> <a href=../../dict/shell/ class=md-nav__link> <span class=md-ellipsis> Shell </span> </a> </li> <li class=md-nav__item> <a href=../../dict/special_file/ class=md-nav__link> <span class=md-ellipsis> Special file </span> </a> </li> <li class=md-nav__item> <a href=../../dict/symlink/ class=md-nav__link> <span class=md-ellipsis> Symlink </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_4> <label class=md-nav__link for=__nav_4 id=__nav_4_label tabindex=0> <span class=md-ellipsis> Howto </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_4_label aria-expanded=false> <label class=md-nav__title for=__nav_4> <span class="md-nav__icon md-icon"></span> Howto </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../howto/calculate-dc/ class=md-nav__link> <span class=md-ellipsis> Calculating with dc </span> </a> </li> <li class=md-nav__item> <a href=../../howto/collapsing_functions/ class=md-nav__link> <span class=md-ellipsis> Collapsing Functions </span> </a> </li> <li class=md-nav__item> <a href=../../howto/conffile/ class=md-nav__link> <span class=md-ellipsis> Config files for your script </span> </a> </li> <li class=md-nav__item> <a href=../../howto/dissectabadoneliner/ class=md-nav__link> <span class=md-ellipsis> Dissect a bad oneliner </span> </a> </li> <li class=md-nav__item> <a href=../../howto/edit-ed/ class=md-nav__link> <span class=md-ellipsis> Editing files via scripts with ed </span> </a> </li> <li class=md-nav__item> <a href=../../howto/getopts_tutorial/ class=md-nav__link> <span class=md-ellipsis> Small getopts tutorial </span> </a> </li> <li class=md-nav__item> <a href=../../howto/mutex/ class=md-nav__link> <span class=md-ellipsis> Lock your script (against parallel execution) </span> </a> </li> <li class=md-nav__item> <a href=../../howto/pax/ class=md-nav__link> <span class=md-ellipsis> pax - the POSIX archiver </span> </a> </li> <li class=md-nav__item> <a href=../../howto/redirection_tutorial/ class=md-nav__link> <span class=md-ellipsis> Illustrated Redirection Tutorial </span> </a> </li> <li class=md-nav__item> <a href=../../howto/testing-your-scripts/ class=md-nav__link> <span class=md-ellipsis> Testing your scripts </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_5> <label class=md-nav__link for=__nav_5 id=__nav_5_label tabindex=0> <span class=md-ellipsis> Internals </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_5_label aria-expanded=false> <label class=md-nav__title for=__nav_5> <span class="md-nav__icon md-icon"></span> Internals </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../internals/shell_options/ class=md-nav__link> <span class=md-ellipsis> List of shell options </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_6> <label class=md-nav__link for=__nav_6 id=__nav_6_label tabindex=0> <span class=md-ellipsis> Misc </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_6_label aria-expanded=false> <label class=md-nav__title for=__nav_6> <span class="md-nav__icon md-icon"></span> Misc </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../misc/bashphorisms/ class=md-nav__link> <span class=md-ellipsis> The Bashphorisms </span> </a> </li> <li class=md-nav__item> <a href=../../misc/readthesourceluke/ class=md-nav__link> <span class=md-ellipsis> Readthesourceluke </span> </a> </li> <li class=md-nav__item> <a href=../../misc/shell_humor/ class=md-nav__link> <span class=md-ellipsis> Shell Humor </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_7> <label class=md-nav__link for=__nav_7 id=__nav_7_label tabindex=0> <span class=md-ellipsis> Scripting </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_7_label aria-expanded=false> <label class=md-nav__title for=__nav_7> <span class="md-nav__icon md-icon"></span> Scripting </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../scripting/bashbehaviour/ class=md-nav__link> <span class=md-ellipsis> Bash's behaviour </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/bashchanges/ class=md-nav__link> <span class=md-ellipsis> Bash changes </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/basics/ class=md-nav__link> <span class=md-ellipsis> The basics of shell scripting </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/debuggingtips/ class=md-nav__link> <span class=md-ellipsis> Debugging a script </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/newbie_traps/ class=md-nav__link> <span class=md-ellipsis> Beginner Mistakes </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/nonportable/ class=md-nav__link> <span class=md-ellipsis> Portability talk </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/obsolete/ class=md-nav__link> <span class=md-ellipsis> Obsolete and deprecated syntax </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/posparams/ class=md-nav__link> <span class=md-ellipsis> Handling positional parameters </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/processtree/ class=md-nav__link> <span class=md-ellipsis> Bash and the process tree </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/style/ class=md-nav__link> <span class=md-ellipsis> Scripting with style </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/terminalcodes/ class=md-nav__link> <span class=md-ellipsis> Terminal codes (ANSI/VT100) introduction </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_8> <label class=md-nav__link for=__nav_8 id=__nav_8_label tabindex=0> <span class=md-ellipsis> Snipplets </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_8_label aria-expanded=false> <label class=md-nav__title for=__nav_8> <span class="md-nav__icon md-icon"></span> Snipplets </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../snipplets/ class=md-nav__link> <span class=md-ellipsis> Small code snipplets </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/add_color_to_your_scripts/ class=md-nav__link> <span class=md-ellipsis> Add Color to your scripts </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/awkcsv/ class=md-nav__link> <span class=md-ellipsis> Using awk to deal with CSV that uses quoted/unquoted delimiters </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/filesize/ class=md-nav__link> <span class=md-ellipsis> Show size of a file </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/kill_bg_job_without_message/ class=md-nav__link> <span class=md-ellipsis> Kill a background job without a message </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/largestfile/ class=md-nav__link> <span class=md-ellipsis> Get largest file </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/pause_command/ class=md-nav__link> <span class=md-ellipsis> Pausing a script (like MSDOS pause command) </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/prargs/ class=md-nav__link> <span class=md-ellipsis> Print argument list for testing </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/print_horizontal_line/ class=md-nav__link> <span class=md-ellipsis> Print a horizontal line </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/rndstr/ class=md-nav__link> <span class=md-ellipsis> Print a random string or select random elements </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/screen_saverestore/ class=md-nav__link> <span class=md-ellipsis> Save and restore terminal/screen content </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/ssh_fetchkeys/ class=md-nav__link> <span class=md-ellipsis> Fetching SSH hostkeys without interaction </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/ssh_local_var/ class=md-nav__link> <span class=md-ellipsis> Run some bash commands with SSH remotely using local variables </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/wrapperargs/ class=md-nav__link> <span class=md-ellipsis> Generate code with own arguments properly quoted </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/xclip/ class=md-nav__link> <span class=md-ellipsis> X-Clipboard on Commandline </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9> <label class=md-nav__link for=__nav_9 id=__nav_9_label tabindex=0> <span class=md-ellipsis> Syntax </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_9_label aria-expanded=false> <label class=md-nav__title for=__nav_9> <span class="md-nav__icon md-icon"></span> Syntax </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../syntax/arith_expr/ class=md-nav__link> <span class=md-ellipsis> Arithmetic expressions </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/arrays/ class=md-nav__link> <span class=md-ellipsis> Arrays </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/basicgrammar/ class=md-nav__link> <span class=md-ellipsis> Basic grammar rules of Bash </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/pattern/ class=md-nav__link> <span class=md-ellipsis> Patterns and pattern matching </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/pe/ class=md-nav__link> <span class=md-ellipsis> Parameter expansion </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/quoting/ class=md-nav__link> <span class=md-ellipsis> Quotes and escaping </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/redirection/ class=md-nav__link> <span class=md-ellipsis> Redirection </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/shellvars/ class=md-nav__link> <span class=md-ellipsis> Special parameters and shell variables </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/words/ class=md-nav__link> <span class=md-ellipsis> Words... </span> </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_10> <label class=md-nav__link for=__nav_9_10 id=__nav_9_10_label tabindex=0> <span class=md-ellipsis> Ccmd </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_10_label aria-expanded=false> <label class=md-nav__title for=__nav_9_10> <span class="md-nav__icon md-icon"></span> Ccmd </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../syntax/ccmd/arithmetic_eval/ class=md-nav__link> <span class=md-ellipsis> Arithmetic evaluation (command) </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/c_for/ class=md-nav__link> <span class=md-ellipsis> The C-style for-loop </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/case/ class=md-nav__link> <span class=md-ellipsis> The case statement </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/classic_for/ class=md-nav__link> <span class=md-ellipsis> The classic for-loop </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/conditional_expression/ class=md-nav__link> <span class=md-ellipsis> The conditional expression </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/grouping_plain/ class=md-nav__link> <span class=md-ellipsis> Grouping commands </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/grouping_subshell/ class=md-nav__link> <span class=md-ellipsis> Grouping commands in a subshell </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/if_clause/ class=md-nav__link> <span class=md-ellipsis> The if-clause </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/intro/ class=md-nav__link> <span class=md-ellipsis> Bash compound commands </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/until_loop/ class=md-nav__link> <span class=md-ellipsis> The until loop </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/user_select/ class=md-nav__link> <span class=md-ellipsis> User selections </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/ccmd/while_loop/ class=md-nav__link> <span class=md-ellipsis> The while-loop </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_11> <label class=md-nav__link for=__nav_9_11 id=__nav_9_11_label tabindex=0> <span class=md-ellipsis> Expansion </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_11_label aria-expanded=false> <label class=md-nav__title for=__nav_9_11> <span class="md-nav__icon md-icon"></span> Expansion </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../syntax/expansion/arith/ class=md-nav__link> <span class=md-ellipsis> Arithmetic expansion </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/brace/ class=md-nav__link> <span class=md-ellipsis> Brace expansion </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/cmdsubst/ class=md-nav__link> <span class=md-ellipsis> Command substitution </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/globs/ class=md-nav__link> <span class=md-ellipsis> Pathname expansion (globbing) </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/intro/ class=md-nav__link> <span class=md-ellipsis> Expansions and substitutions </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/proc_subst/ class=md-nav__link> <span class=md-ellipsis> Process substitution </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/tilde/ class=md-nav__link> <span class=md-ellipsis> Tilde expansion </span> </a> </li> <li class=md-nav__item> <a href=../../syntax/expansion/wordsplit/ class=md-nav__link> <span class=md-ellipsis> Word splitting </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_12> <label class=md-nav__link for=__nav_9_12 id=__nav_9_12_label tabindex=0> <span class=md-ellipsis> Grammar </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_12_label aria-expanded=false> <label class=md-nav__title for=__nav_9_12> <span class="md-nav__icon md-icon"></span> Grammar </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../syntax/grammar/parser_exec/ class=md-nav__link> <span class=md-ellipsis> Parser exec </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_13> <label class=md-nav__link for=__nav_9_13 id=__nav_9_13_label tabindex=0> <span class=md-ellipsis> Keywords </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_13_label aria-expanded=false> <label class=md-nav__title for=__nav_9_13> <span class="md-nav__icon md-icon"></span> Keywords </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../syntax/keywords/coproc/ class=md-nav__link> <span class=md-ellipsis> The coproc keyword </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=../../tags/ class=md-nav__link> <span class=md-ellipsis> Tags </span> </a> </li> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component=sidebar data-md-type=toc> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#general-syntax class=md-nav__link> <span class=md-ellipsis> General syntax </span> </a> </li> <li class=md-nav__item> <a href=#file-tests class=md-nav__link> <span class=md-ellipsis> File tests </span> </a> </li> <li class=md-nav__item> <a href=#string-tests class=md-nav__link> <span class=md-ellipsis> String tests </span> </a> </li> <li class=md-nav__item> <a href=#arithmetic-tests class=md-nav__link> <span class=md-ellipsis> Arithmetic tests </span> </a> </li> <li class=md-nav__item> <a href=#misc-syntax class=md-nav__link> <span class=md-ellipsis> Misc syntax </span> </a> </li> <li class=md-nav__item> <a href=#number-of-arguments-rules class=md-nav__link> <span class=md-ellipsis> Number of Arguments Rules </span> </a> </li> <li class=md-nav__item> <a href=#and-and-or class=md-nav__link> <span class=md-ellipsis> AND and OR </span> </a> <nav class=md-nav aria-label="AND and OR"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#the-prefered-way class=md-nav__link> <span class=md-ellipsis> The Prefered Way </span> </a> </li> <li class=md-nav__item> <a href=#the-other-way-a-and-o class=md-nav__link> <span class=md-ellipsis> The other way: -a and -o </span> </a> </li> <li class=md-nav__item> <a href=#why-you-should-avoid-using-a-and-o class=md-nav__link> <span class=md-ellipsis> Why you should avoid using -a and -o </span> </a> <nav class=md-nav aria-label="Why you should avoid using -a and -o"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#if-portability-is-a-concern class=md-nav__link> <span class=md-ellipsis> If portability is a concern </span> </a> </li> <li class=md-nav__item> <a href=#if-you-want-the-cut-behaviour class=md-nav__link> <span class=md-ellipsis> If you want the cut behaviour </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#precedence-and-parenthesis class=md-nav__link> <span class=md-ellipsis> Precedence and Parenthesis </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#not class=md-nav__link> <span class=md-ellipsis> NOT </span> </a> </li> <li class=md-nav__item> <a href=#pitfalls-summarized class=md-nav__link> <span class=md-ellipsis> Pitfalls summarized </span> </a> <nav class=md-nav aria-label="Pitfalls summarized"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#general class=md-nav__link> <span class=md-ellipsis> General </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#code-examples class=md-nav__link> <span class=md-ellipsis> Code examples </span> </a> <nav class=md-nav aria-label="Code examples"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#snipplets class=md-nav__link> <span class=md-ellipsis> Snipplets </span> </a> </li> <li class=md-nav__item> <a href=#listing-directories class=md-nav__link> <span class=md-ellipsis> Listing directories </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#see-also class=md-nav__link> <span class=md-ellipsis> See also </span> </a> </li> </ul> </nav> </div> </div> </div> <div class=md-content data-md-component=content> <article class="md-content__inner md-typeset"> <a href=https://github.com/flokoe/bash-hackers-wiki/edit/main/docs/commands/classictest.md title="Edit this page" class="md-content__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z"/></svg> </a> <a href=https://github.com/flokoe/bash-hackers-wiki/raw/main/docs/commands/classictest.md title="View source of this page" class="md-content__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.2 8.2 0 0 1-1.23-2"/></svg> </a> <h1 id=the-classic-test-command>The classic test command<a class=headerlink href=#the-classic-test-command title="Permanent link">&para;</a></h1> <p><code>test &lt;EXPRESSION&gt;</code></p> <p><code>[ &lt;EXPRESSION&gt; ]</code></p> <h2 id=general-syntax>General syntax<a class=headerlink href=#general-syntax title="Permanent link">&para;</a></h2> <p>This command allows you to do various tests and sets its exit code to 0 (<code>true</code>) or 1 (<code>false</code>) whenever such a test succeeds or not. Using this exit code, it's possible to let Bash react on the result of such a test, here by using the command in an if-statement:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-0-1 name=__codelineno-0-1 href=#__codelineno-0-1></a><span class=ch>#!/bin/bash</span>
<a id=__codelineno-0-2 name=__codelineno-0-2 href=#__codelineno-0-2></a>
<a id=__codelineno-0-3 name=__codelineno-0-3 href=#__codelineno-0-3></a><span class=c1># test if /etc/passwd exists</span>
<a id=__codelineno-0-4 name=__codelineno-0-4 href=#__codelineno-0-4></a><span class=k>if</span><span class=w> </span><span class=nb>test</span><span class=w> </span>-e<span class=w> </span>/etc/passwd<span class=p>;</span><span class=w> </span><span class=k>then</span>
<a id=__codelineno-0-5 name=__codelineno-0-5 href=#__codelineno-0-5></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;Alright man...&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-0-6 name=__codelineno-0-6 href=#__codelineno-0-6></a><span class=k>else</span>
<a id=__codelineno-0-7 name=__codelineno-0-7 href=#__codelineno-0-7></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;Yuck! Where is it??&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-0-8 name=__codelineno-0-8 href=#__codelineno-0-8></a><span class=w> </span><span class=nb>exit</span><span class=w> </span><span class=m>1</span>
<a id=__codelineno-0-9 name=__codelineno-0-9 href=#__codelineno-0-9></a><span class=k>fi</span>
</code></pre></div> <p>The syntax of the test command is relatively easy. Usually it's the command name <code>test</code> followed by a test type (here <code>-e</code> for "file exists") followed by test-type-specific values (here the filename to check, <code>/etc/passwd</code>).</p> <p>There's a second standardized command that does exactly the same: the command <code>[</code> the difference just is that it's called <code>[</code> and the last argument to the command must be a <code>]</code>: It forms <code>[ &lt;EXPRESSION&gt; ]</code>.</p> <p>Let's rewrite the above example to use it:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-1-1 name=__codelineno-1-1 href=#__codelineno-1-1></a><span class=ch>#!/bin/bash</span>
<a id=__codelineno-1-2 name=__codelineno-1-2 href=#__codelineno-1-2></a>
<a id=__codelineno-1-3 name=__codelineno-1-3 href=#__codelineno-1-3></a><span class=c1># test if /etc/passwd exists</span>
<a id=__codelineno-1-4 name=__codelineno-1-4 href=#__codelineno-1-4></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span>/etc/passwd<span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span>
<a id=__codelineno-1-5 name=__codelineno-1-5 href=#__codelineno-1-5></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;Alright man...&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-1-6 name=__codelineno-1-6 href=#__codelineno-1-6></a><span class=k>else</span>
<a id=__codelineno-1-7 name=__codelineno-1-7 href=#__codelineno-1-7></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;Yuck! Where is it??&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-1-8 name=__codelineno-1-8 href=#__codelineno-1-8></a><span class=w> </span><span class=nb>exit</span><span class=w> </span><span class=m>1</span>
<a id=__codelineno-1-9 name=__codelineno-1-9 href=#__codelineno-1-9></a><span class=k>fi</span>
</code></pre></div> <p>One might <strong>think</strong> now that these <code>[</code> and <code>]</code> belong to the syntax of Bash's if-clause: <strong>No they don't! It's a simple, ordinary command, still!</strong></p> <p>Another thing you have to remember is that if the test command wants one parameter for a test, you have to give it one parameter. Let's check for some of your music files:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-2-1 name=__codelineno-2-1 href=#__codelineno-2-1></a><span class=ch>#!/bin/bash</span>
<a id=__codelineno-2-2 name=__codelineno-2-2 href=#__codelineno-2-2></a>
<a id=__codelineno-2-3 name=__codelineno-2-3 href=#__codelineno-2-3></a><span class=nv>mymusic</span><span class=o>=</span><span class=s2>&quot;/data/music/Van Halen/Van Halen - Right Now.mp3&quot;</span>
<a id=__codelineno-2-4 name=__codelineno-2-4 href=#__codelineno-2-4></a>
<a id=__codelineno-2-5 name=__codelineno-2-5 href=#__codelineno-2-5></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span><span class=s2>&quot;</span><span class=nv>$mymusic</span><span class=s2>&quot;</span><span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span>
<a id=__codelineno-2-6 name=__codelineno-2-6 href=#__codelineno-2-6></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;Let&#39;s rock&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-2-7 name=__codelineno-2-7 href=#__codelineno-2-7></a><span class=k>else</span>
<a id=__codelineno-2-8 name=__codelineno-2-8 href=#__codelineno-2-8></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;No music today, sorry...&quot;</span><span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span>
<a id=__codelineno-2-9 name=__codelineno-2-9 href=#__codelineno-2-9></a><span class=w> </span><span class=nb>exit</span><span class=w> </span><span class=m>1</span>
<a id=__codelineno-2-10 name=__codelineno-2-10 href=#__codelineno-2-10></a><span class=k>fi</span>
</code></pre></div> <p>As you definitely noted, the filename contains spaces. Since we call a normal ordinary command (<code>test</code> or <code>[</code>) the shell will word-split the expansion of the variable <code>mymusic</code>: You need to quote it when you don't want the <code>test</code>-command to complain about too many arguments for this test-type! If you didn't understand it, please read the <a href=../../syntax/words/ >article about words...</a>.</p> <p>Please also note that the file-tests want <strong>one filename</strong> to test. Don't give a glob (filename-wildcards) as it can expand to many filenames =&gt; <strong>too many arguments!</strong></p> <p><strong>Another common mistake</strong> is to provide too <strong>few</strong> arguments:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-3-1 name=__codelineno-3-1 href=#__codelineno-3-1></a><span class=o>[</span><span class=w> </span><span class=s2>&quot;</span><span class=nv>$mystring</span><span class=s2>&quot;</span>!<span class=o>=</span><span class=s2>&quot;test&quot;</span><span class=w> </span><span class=o>]</span>
</code></pre></div> <p>This provides exactly <strong>one</strong> test-argument to the command. With one parameter, it defaults to the <code>-n</code> test: It tests if a provided string is empty (<code>FALSE</code>) or not (<code>TRUE</code>) - due to the lack of <strong>spaces to separate the arguments</strong> the shown command always ends <code>TRUE</code>!</p> <p>Well, I addressed several basic rules, now let's see what the test-command can do for you. The Bash test-types can be split into several sections: <strong>file tests</strong>, <strong>string tests</strong>, <strong>arithmetic tests</strong>, <strong>misc tests</strong>. Below, the tests marked with <img alt= class=twemoji src=https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/26a0.svg title=:warning:> are non-standard tests (i.e. not in SUS/POSIX/etc..).</p> <h2 id=file-tests>File tests<a class=headerlink href=#file-tests title="Permanent link">&para;</a></h2> <p>This section probably holds the most tests, I'll list them in some logical order. Since Bash 4.1, all tests related to permissions respect ACLs, if the underlying filesystem/OS supports them.</p> <table> <thead> <tr> <th>Operator syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><strong>-a</strong> <file></td> <td>True if <file> exists. <img alt= class=twemoji src=https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/26a0.svg title=:warning:> (not recommended, may collide with <code>-a</code> for <code>AND</code>, see below)</td> </tr> <tr> <td><strong>-e</strong> <file></td> <td>True if <file> exists.</td> </tr> <tr> <td><strong>-f</strong> <file></td> <td>True, if <file> exists and is a <strong>regular</strong> file.</td> </tr> <tr> <td><strong>-d</strong> <file></td> <td>True, if <file> exists and is a <strong>directory</strong>.</td> </tr> <tr> <td><strong>-c</strong> <file></td> <td>True, if <file> exists and is a <strong>character special</strong> file.</td> </tr> <tr> <td><strong>-b</strong> <file></td> <td>True, if <file> exists and is a <strong>block special</strong> file.</td> </tr> <tr> <td><strong>-p</strong> <file></td> <td>True, if <file> exists and is a <strong>named pipe</strong> (FIFO).</td> </tr> <tr> <td><strong>-S</strong> <file></td> <td>True, if <file> exists and is a <strong>socket</strong> file.</td> </tr> <tr> <td><strong>-L</strong> <file></td> <td>True, if <file> exists and is a <strong>symbolic link</strong>.</td> </tr> <tr> <td><strong>-h</strong> <file></td> <td>True, if <file> exists and is a <strong>symbolic link</strong>.</td> </tr> <tr> <td><strong>-g</strong> <file></td> <td>True, if <file> exists and has <strong>sgid bit</strong> set.</td> </tr> <tr> <td><strong>-u</strong> <file></td> <td>True, if <file> exists and has <strong>suid bit</strong> set.</td> </tr> <tr> <td><strong>-r</strong> <file></td> <td>True, if <file> exists and is <strong>readable</strong>.</td> </tr> <tr> <td><strong>-w</strong> <file></td> <td>True, if <file> exists and is <strong>writable</strong>.</td> </tr> <tr> <td><strong>-x</strong> <file></td> <td>True, if <file> exists and is <strong>executable</strong>.</td> </tr> <tr> <td><strong>-s</strong> <file></td> <td>True, if <file> exists and has size bigger than 0 (<strong>not empty</strong>).</td> </tr> <tr> <td><strong>-t</strong> <fd></td> <td>True, if file descriptor <fd> is open and refers to a terminal.</td> </tr> <tr> <td><file1> <strong>-nt</strong> <file2></td> <td>True, if <file1> is <strong>newer than</strong> <file2> (mtime). <img alt= class=twemoji src=https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/26a0.svg title=:warning:></td> </tr> <tr> <td><file1> <strong>-ot</strong> <file2></td> <td>True, if <file1> is <strong>older than</strong> <file2> (mtime). <img alt= class=twemoji src=https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/26a0.svg title=:warning:></td> </tr> <tr> <td><file1> <strong>-ef</strong> <file2></td> <td>True, if <file1> and <file2> refer to the <strong>same device and inode numbers</strong>. <img alt= class=twemoji src=https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/26a0.svg title=:warning:></td> </tr> </tbody> </table> <h2 id=string-tests>String tests<a class=headerlink href=#string-tests title="Permanent link">&para;</a></h2> <table> <thead> <tr> <th>Operator syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><strong>-z</strong> <string></td> <td>True, if <string> is <strong>empty</strong>.</td> </tr> <tr> <td><strong>-n</strong> <string></td> <td>True, if <string> is <strong>not empty</strong> (this is the default operation).</td> </tr> <tr> <td><string1> <strong>=</strong> <string2></td> <td>True, if the strings are <strong>equal</strong>.</td> </tr> <tr> <td><string1> <strong>!=</strong> <string2></td> <td>True, if the strings are <strong>not equal</strong>.</td> </tr> <tr> <td><string1> <strong>&lt;</strong> <string2></td> <td>True if <string1> sorts <strong>before</strong> <string2> lexicographically (pure ASCII, not current locale!). Remember to escape! Use <code>&lt;</code></td> </tr> <tr> <td><string1> <strong>&gt;</strong> <string2></td> <td>True if <string1> sorts <strong>after</strong> <string2> lexicographically (pure ASCII, not current locale!). Remember to escape! Use <code>&gt;</code></td> </tr> </tbody> </table> <h2 id=arithmetic-tests>Arithmetic tests<a class=headerlink href=#arithmetic-tests title="Permanent link">&para;</a></h2> <table> <thead> <tr> <th>Operator syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><integer1> <strong>-eq</strong> <integer2></td> <td>True, if the integers are <strong>equal</strong>.</td> </tr> <tr> <td><integer1> <strong>-ne</strong> <integer2></td> <td>True, if the integers are <strong>NOT equal</strong>.</td> </tr> <tr> <td><integer1> <strong>-le</strong> <integer2></td> <td>True, if the first integer is <strong>less than or equal</strong> second one.</td> </tr> <tr> <td><integer1> <strong>-ge</strong> <integer2></td> <td>True, if the first integer is <strong>greater than or equal</strong> second one.</td> </tr> <tr> <td><integer1> <strong>-lt</strong> <integer2></td> <td>True, if the first integer is <strong>less than</strong> second one.</td> </tr> <tr> <td><integer1> <strong>-gt</strong> <integer2></td> <td>True, if the first integer is <strong>greater than</strong> second one.</td> </tr> </tbody> </table> <h2 id=misc-syntax>Misc syntax<a class=headerlink href=#misc-syntax title="Permanent link">&para;</a></h2> <table> <thead> <tr> <th>Operator syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><test1> <strong>-a</strong> <test2></td> <td>True, if <test1> <strong>and</strong> <test2> are true (AND). Note that <code>-a</code> also may be used as a file test (see above)</td> </tr> <tr> <td><test1> <strong>-o</strong> <test2></td> <td>True, if either <test1> <strong>or</strong> <test2> is true (OR).</td> </tr> <tr> <td><strong>!</strong> <test></td> <td>True, if <test> is <strong>false</strong> (NOT).</td> </tr> <tr> <td><strong>(</strong> <test> <strong>)</strong></td> <td>Group a test (for precedence). <strong>Attention:</strong> In normal shell-usage, the <code>(</code> and <code>)</code> must be escaped; use <code>(</code> and <code>)</code>!</td> </tr> <tr> <td><strong>-o</strong> <option_name></td> <td>True, if the <a href=../../internals/shell_options/ >shell option</a> <option_name> is set.</td> </tr> <tr> <td><strong>-v</strong> <variablename></td> <td>True if the variable <variablename> has been set. Use <code>var[n]</code> for array elements.</td> </tr> <tr> <td><strong>-R</strong> <variablename></td> <td>True if the variable <variablename> has been set and is a nameref variable (since 4.3-alpha)</td> </tr> </tbody> </table> <h2 id=number-of-arguments-rules>Number of Arguments Rules<a class=headerlink href=#number-of-arguments-rules title="Permanent link">&para;</a></h2> <p>The <code>test</code> builtin, especially hidden under its <code>[</code> name, may seem simple but is in fact <strong>causing a lot of trouble sometimes</strong>. One of the difficulty is that the behaviour of <code>test</code> not only depends on its arguments but also on the <strong>number of its arguments</strong>.</p> <p>Here are the rules taken from the manual:</p> <div class="admonition note"> <p class=admonition-title>Note</p> <p>This is for the command <code>test</code>, for <code>[</code> the number of arguments is calculated without the final <code>]</code>, for example <code>[ ]</code> follows the "zero arguments" rule.</p> </div> <ul> <li><strong>0 arguments</strong><ul> <li>The expression is false.</li> </ul> </li> <li><strong>1 argument</strong><ul> <li>The expression is true if, and only if, the argument is not null</li> </ul> </li> <li><strong>2 arguments</strong><ul> <li>If the first argument is <code>!</code> (exclamation mark), the expression is true if, and only if, the second argument is null</li> <li>If the first argument is one of the unary conditional operators listed above under the syntax rules, the expression is true if the unary test is true</li> <li>If the first argument is not a valid unary conditional operator, the expression is false</li> </ul> </li> <li><strong>3 arguments</strong><ul> <li>If the second argument is one of the binary conditional operators listed above under the syntax rules, the result of the expression is the result of the binary test using the first and third arguments as operands</li> <li>If the first argument is <code>!</code>, the value is the negation of the two-argument test using the second and third arguments</li> <li>If the first argument is exactly <code>(</code> and the third argument is exactly <code>)</code>, the result is the one-argument test of the second argument. Otherwise, the expression is false. The <code>-a</code> and <code>-o</code> operators are considered binary operators in this case (<strong>Attention:</strong> This means the operator <code>-a</code> is not a file operator in this case!)</li> </ul> </li> <li><strong>4 arguments</strong><ul> <li>If the first argument is <code>!</code>, the result is the negation of the three-argument expression composed of the remaining arguments. Otherwise, the expression is parsed and evaluated according to precedence using the rules listed above</li> </ul> </li> <li><strong>5 or more arguments</strong><ul> <li>The expression is parsed and evaluated according to precedence using the rules listed above</li> </ul> </li> </ul> <p>These rules may seem complex, but it's not so bad in practice. Knowing them might help you to explain some of the "unexplicable" behaviours you might encounter:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-4-1 name=__codelineno-4-1 href=#__codelineno-4-1></a><span class=nv>var</span><span class=o>=</span><span class=s2>&quot;&quot;</span>
<a id=__codelineno-4-2 name=__codelineno-4-2 href=#__codelineno-4-2></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-n<span class=w> </span><span class=nv>$var</span><span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;var is not empty&quot;</span><span class=p>;</span><span class=w> </span><span class=k>fi</span>
</code></pre></div> <p>This code prints "var is not empty", even though <code>-n something</code> is supposed to be true if <code>$var</code> is not empty - <strong>why?</strong></p> <p>Here, as <code>$var</code> is <strong>not quoted</strong>, word splitting occurs and <code>$var</code> results in actually nothing (Bash removes it from the command's argument list!). So the test is in fact <code>[ -n ]</code> <strong>and falls into the "one argument" rule</strong>, the only argument is "-n" which is not null and so the test returns true. The solution, as usual, is to <strong>quote the parameter expansion</strong>: <code>[ -n "$var" ]</code> so that the test has always 2 arguments, even if the second one is the null string.</p> <p>These rules also explain why, for instance, -a and -o can have several meanings.</p> <h2 id=and-and-or>AND and OR<a class=headerlink href=#and-and-or title="Permanent link">&para;</a></h2> <h3 id=the-prefered-way>The Prefered Way<a class=headerlink href=#the-prefered-way title="Permanent link">&para;</a></h3> <p>The way often recommended to logically connect several tests with AND and OR is to use <strong>several single test commands</strong> and to <strong>combine</strong> them with the shell <code>&amp;&amp;</code> and <code>||</code> <strong>list control operators</strong>.</p> <p>See this:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-5-1 name=__codelineno-5-1 href=#__codelineno-5-1></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-n<span class=w> </span><span class=s2>&quot;</span><span class=nv>$var</span><span class=s2>&quot;</span><span class=o>]</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span><span class=s2>&quot;</span><span class=nv>$var</span><span class=s2>&quot;</span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span>
<a id=__codelineno-5-2 name=__codelineno-5-2 href=#__codelineno-5-2></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;\$var is not null and a file named </span><span class=nv>$var</span><span class=s2> exists!&quot;</span>
<a id=__codelineno-5-3 name=__codelineno-5-3 href=#__codelineno-5-3></a><span class=k>fi</span>
</code></pre></div> <p>The return status of AND and OR lists is the exit status of the last command executed in the list</p> <ul> <li>With <code>command1 &amp;&amp; command2</code>, <code>command2</code> is executed if, and only if, <code>command1</code> returns an exit status of zero (true)</li> <li>With <code>command1 ││ command2</code>, <code>command2</code> is executed if, and only if, <code>command1</code> returns a non-zero exit status (false)</li> </ul> <h3 id=the-other-way-a-and-o>The other way: -a and -o<a class=headerlink href=#the-other-way-a-and-o title="Permanent link">&para;</a></h3> <p>The logical operators AND and OR for the test-command itself are <code>-a</code> and <code>-o</code>, thus:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-6-1 name=__codelineno-6-1 href=#__codelineno-6-1></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-n<span class=w> </span><span class=s2>&quot;</span><span class=nv>$var</span><span class=s2>&quot;</span><span class=w> </span>-a<span class=w> </span>-e<span class=w> </span><span class=s2>&quot;</span><span class=nv>$var</span><span class=s2>&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=p>;</span><span class=w> </span><span class=k>then</span>
<a id=__codelineno-6-2 name=__codelineno-6-2 href=#__codelineno-6-2></a><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;\$var is not null and a file named </span><span class=nv>$var</span><span class=s2> exists&quot;</span>
<a id=__codelineno-6-3 name=__codelineno-6-3 href=#__codelineno-6-3></a><span class=k>fi</span>
</code></pre></div> <p>They are <strong>not</strong> <code>&amp;&amp;</code> or <code>||</code>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-7-1 name=__codelineno-7-1 href=#__codelineno-7-1></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-n<span class=w> </span><span class=s2>&quot;/tmp&quot;</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span>-d<span class=w> </span><span class=s2>&quot;/tmp&quot;</span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>fi</span><span class=w> </span><span class=c1># DOES NOT WORK</span>
<a id=__codelineno-7-2 name=__codelineno-7-2 href=#__codelineno-7-2></a>bash:<span class=w> </span><span class=o>[</span>:<span class=w> </span>missing<span class=w> </span><span class=sb>`</span><span class=o>]</span><span class=err>&#39;</span>
</code></pre></div> <p>You might find the error message confusing, <code>[</code> does not find the required final <code>]</code>, because as seen above <code>&amp;&amp;</code> is used to write a <strong>list of commands</strong>. The <code>if</code> statement actually <strong>sees two commands</strong>:</p> <ul> <li><code>[ -n "/tmp"</code></li> <li><code>-d "/tmp" ]</code></li> </ul> <p>...which <strong>must</strong> fail.</p> <h3 id=why-you-should-avoid-using-a-and-o>Why you should avoid using -a and -o<a class=headerlink href=#why-you-should-avoid-using-a-and-o title="Permanent link">&para;</a></h3> <h4 id=if-portability-is-a-concern>If portability is a concern<a class=headerlink href=#if-portability-is-a-concern title="Permanent link">&para;</a></h4> <p>POSIX&reg;/SUSv3 does <strong>not</strong> specify the behaviour of <code>test</code> in cases where there are more than 4 arguments. If you write a script that might not be executed by Bash, the behaviour might be different! <sup id=fnref:1><a class=footnote-ref href=#fn:1>1</a></sup></p> <h4 id=if-you-want-the-cut-behaviour>If you want the cut behaviour<a class=headerlink href=#if-you-want-the-cut-behaviour title="Permanent link">&para;</a></h4> <p>Let's say, we want to check the following two things (AND):</p> <ol> <li>if a string is null (empty)</li> <li>if a command produced an output</li> </ol> <p>Let's see:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-8-1 name=__codelineno-8-1 href=#__codelineno-8-1></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-z<span class=w> </span><span class=s2>&quot;false&quot;</span><span class=w> </span>-a<span class=w> </span>-z<span class=w> </span><span class=s2>&quot;</span><span class=k>$(</span><span class=nb>echo</span><span class=w> </span>I<span class=w> </span>am<span class=w> </span>executed<span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span><span class=k>)</span><span class=s2>&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span>...<span class=w> </span>
</code></pre></div> <p>=&gt; The arguments are all expanded <strong>before</strong> <code>test</code> runs, thus the echo-command <strong>is executed</strong>.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-9-1 name=__codelineno-9-1 href=#__codelineno-9-1></a><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span>-z<span class=w> </span><span class=s2>&quot;false&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span><span class=o>[</span><span class=w> </span>-z<span class=w> </span><span class=s2>&quot;</span><span class=k>$(</span><span class=nb>echo</span><span class=w> </span>I<span class=w> </span>am<span class=w> </span>not<span class=w> </span>executed<span class=w> </span>&gt;<span class=p>&amp;</span><span class=m>2</span><span class=k>)</span><span class=s2>&quot;</span><span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span>...<span class=w> </span>
</code></pre></div> <p>=&gt; Due to the nature of the <code>&amp;&amp;</code> list operator, the second test-command runs only if the first test-command returns true, our echo-command <strong>is not executed</strong>.</p> <div class="admonition note"> <p class=admonition-title>Note</p> <p>In my opinion, <code>-a</code> and <code>-o</code> are also less readable <code>[pgas]</code></p> </div> <h3 id=precedence-and-parenthesis>Precedence and Parenthesis<a class=headerlink href=#precedence-and-parenthesis title="Permanent link">&para;</a></h3> <p>Take care if you convert your scripts from using <code>-a</code> and <code>-o</code> to use the list way (<code>&amp;&amp;</code> and <code>||</code>):</p> <ul> <li>in the test-command rules, <code>-a</code> has <strong>precedence over</strong> <code>-o</code></li> <li>in the shell grammar rules, <code>&amp;&amp;</code> and <code>||</code> have <strong>equal precedence</strong></li> </ul> <p>That means, <strong>you can get different results</strong>, depending on the manner of use:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-10-1 name=__codelineno-10-1 href=#__codelineno-10-1></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span><span class=s2>&quot;true&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>||</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>false<span class=p>;</span><span class=w> </span><span class=k>fi</span>
<a id=__codelineno-10-2 name=__codelineno-10-2 href=#__codelineno-10-2></a><span class=nb>false</span>
<a id=__codelineno-10-3 name=__codelineno-10-3 href=#__codelineno-10-3></a>
<a id=__codelineno-10-4 name=__codelineno-10-4 href=#__codelineno-10-4></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span><span class=s2>&quot;true&quot;</span><span class=w> </span>-o<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span>-a<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>false<span class=p>;</span><span class=k>fi</span>
<a id=__codelineno-10-5 name=__codelineno-10-5 href=#__codelineno-10-5></a><span class=nb>true</span>
</code></pre></div> <p>As a result you have to think about it a little or add precedence control (parenthesis).</p> <p>For <code>&amp;&amp;</code> and <code>||</code> parenthesis means (shell-ly) grouping the commands, and since <code>( ... )</code> introduces a subshell we will use <code>{ ... }</code> instead:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-11-1 name=__codelineno-11-1 href=#__codelineno-11-1></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span><span class=s2>&quot;true&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>||</span><span class=w> </span><span class=o>{</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span><span class=o>[</span><span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=w> </span><span class=p>;</span><span class=o>}</span><span class=w> </span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>false<span class=p>;</span><span class=w> </span><span class=k>fi</span>
<a id=__codelineno-11-2 name=__codelineno-11-2 href=#__codelineno-11-2></a><span class=nb>true</span>
</code></pre></div> <p>For the test command, the precedence parenthesis are, as well, <code>( )</code>, but you need to escape or quote them, so that the shell doesn't try to interpret them:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-12-1 name=__codelineno-12-1 href=#__codelineno-12-1></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span><span class=o>(</span><span class=w> </span><span class=s2>&quot;true&quot;</span><span class=w> </span>-o<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>)</span><span class=w> </span>-a<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>false<span class=p>;</span><span class=w> </span><span class=k>fi</span>
<a id=__codelineno-12-2 name=__codelineno-12-2 href=#__codelineno-12-2></a><span class=nb>false</span>
<a id=__codelineno-12-3 name=__codelineno-12-3 href=#__codelineno-12-3></a>
<a id=__codelineno-12-4 name=__codelineno-12-4 href=#__codelineno-12-4></a><span class=c1># equivalent, but less readable IMHO:</span>
<a id=__codelineno-12-5 name=__codelineno-12-5 href=#__codelineno-12-5></a>$<span class=w> </span><span class=k>if</span><span class=w> </span><span class=o>[</span><span class=w> </span><span class=s1>&#39;(&#39;</span><span class=w> </span><span class=s2>&quot;true&quot;</span><span class=w> </span>-o<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=s1>&#39;)&#39;</span><span class=w> </span>-a<span class=w> </span>-e<span class=w> </span>/does/not/exist<span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>true<span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span>false<span class=p>;</span><span class=w> </span><span class=k>fi</span>
<a id=__codelineno-12-6 name=__codelineno-12-6 href=#__codelineno-12-6></a><span class=nb>false</span>
</code></pre></div> <h2 id=not>NOT<a class=headerlink href=#not title="Permanent link">&para;</a></h2> <p>As for AND and OR, there are 2 ways to negate a test with the shell keyword <code>!</code> or passing <code>!</code> as an argument to <code>test</code>.</p> <p>Here <code>!</code> negates the exit status of the command <code>test</code> which is 0 (true), and the else part is executed:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-13-1 name=__codelineno-13-1 href=#__codelineno-13-1></a><span class=k>if</span><span class=w> </span>!<span class=w> </span><span class=o>[</span><span class=w> </span>-d<span class=w> </span><span class=s1>&#39;/tmp&#39;</span><span class=w> </span><span class=o>]</span><span class=p>;</span><span class=w> </span><span class=k>then</span><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;/tmp doesn&#39;t exists&quot;</span><span class=p>;</span><span class=w> </span><span class=k>else</span><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;/tmp exists&quot;</span><span class=p>;</span><span class=w> </span><span class=k>fi</span>
</code></pre></div> <p>Here the <code>test</code> command itself exits with status 1 (false) and the else is also executed:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-14-1 name=__codelineno-14-1 href=#__codelineno-14-1></a>if [ ! -d &#39;/tmp&#39; ]; then echo &quot;/tmp doesn&#39;t exists&quot;; else echo &quot;/tmp exists&quot;; fi
</code></pre></div> <p>Unlike for AND and OR, both methods for NOT have an identical behaviour, at least for doing one single test.</p> <h2 id=pitfalls-summarized>Pitfalls summarized<a class=headerlink href=#pitfalls-summarized title="Permanent link">&para;</a></h2> <p>In this section you will get all the mentioned (and maybe more) possible pitfalls and problems in a summary.</p> <h3 id=general>General<a class=headerlink href=#general title="Permanent link">&para;</a></h3> <p>Here's the copy of a mail on bug-bash list. A user asking a question about using the test command in Bash, <strong>he's talking about a problem, which you may have already had yourself</strong>:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-15-1 name=__codelineno-15-1 href=#__codelineno-15-1></a>From: (PROTECTED)
<a id=__codelineno-15-2 name=__codelineno-15-2 href=#__codelineno-15-2></a>Subject: -d option not working. . .?
<a id=__codelineno-15-3 name=__codelineno-15-3 href=#__codelineno-15-3></a>Date: Tue, 11 Sep 2007 21:51:59 -0400
<a id=__codelineno-15-4 name=__codelineno-15-4 href=#__codelineno-15-4></a>To: bug-bash@gnu.org
<a id=__codelineno-15-5 name=__codelineno-15-5 href=#__codelineno-15-5></a>
<a id=__codelineno-15-6 name=__codelineno-15-6 href=#__codelineno-15-6></a>Hi All,
<a id=__codelineno-15-7 name=__codelineno-15-7 href=#__codelineno-15-7></a>
<a id=__codelineno-15-8 name=__codelineno-15-8 href=#__codelineno-15-8></a>I&#39;ve got a script that I&#39;m trying to set up, but it keeps telling me
<a id=__codelineno-15-9 name=__codelineno-15-9 href=#__codelineno-15-9></a>that &quot;[-d command not found&quot;. Can someone please explain what is
<a id=__codelineno-15-10 name=__codelineno-15-10 href=#__codelineno-15-10></a>wrong with this?:
<a id=__codelineno-15-11 name=__codelineno-15-11 href=#__codelineno-15-11></a>
<a id=__codelineno-15-12 name=__codelineno-15-12 href=#__codelineno-15-12></a>
<a id=__codelineno-15-13 name=__codelineno-15-13 href=#__codelineno-15-13></a>
<a id=__codelineno-15-14 name=__codelineno-15-14 href=#__codelineno-15-14></a>
<a id=__codelineno-15-15 name=__codelineno-15-15 href=#__codelineno-15-15></a>#!/bin/sh
<a id=__codelineno-15-16 name=__codelineno-15-16 href=#__codelineno-15-16></a>
<a id=__codelineno-15-17 name=__codelineno-15-17 href=#__codelineno-15-17></a>for i in $*
<a id=__codelineno-15-18 name=__codelineno-15-18 href=#__codelineno-15-18></a>do
<a id=__codelineno-15-19 name=__codelineno-15-19 href=#__codelineno-15-19></a>{
<a id=__codelineno-15-20 name=__codelineno-15-20 href=#__codelineno-15-20></a> if [-d $i]
<a id=__codelineno-15-21 name=__codelineno-15-21 href=#__codelineno-15-21></a> then
<a id=__codelineno-15-22 name=__codelineno-15-22 href=#__codelineno-15-22></a> echo &quot;$i is a directory! Yay!&quot;
<a id=__codelineno-15-23 name=__codelineno-15-23 href=#__codelineno-15-23></a> else
<a id=__codelineno-15-24 name=__codelineno-15-24 href=#__codelineno-15-24></a> echo &quot;$i is not a directory!&quot;
<a id=__codelineno-15-25 name=__codelineno-15-25 href=#__codelineno-15-25></a> fi
<a id=__codelineno-15-26 name=__codelineno-15-26 href=#__codelineno-15-26></a>}
<a id=__codelineno-15-27 name=__codelineno-15-27 href=#__codelineno-15-27></a>done
<a id=__codelineno-15-28 name=__codelineno-15-28 href=#__codelineno-15-28></a>
<a id=__codelineno-15-29 name=__codelineno-15-29 href=#__codelineno-15-29></a>Regards
</code></pre></div> <p>See the problem regarding the used test-command (the other potential problems are not of interest here)?</p> <div class=highlight><pre><span></span><code><a id=__codelineno-16-1 name=__codelineno-16-1 href=#__codelineno-16-1></a><span class=o>[</span>-d<span class=w> </span><span class=nv>$i</span><span class=o>]</span>
</code></pre></div> <p>He simply didn't know that <code>test</code> or <code>[</code> is a normal, simple command. Well, here's the answer he got. I quote it here, because it's a well written text that addresses most of the common issues with the "classic" test command:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-17-1 name=__codelineno-17-1 href=#__codelineno-17-1></a>From: Bob Proulx (EMAIL PROTECTED)
<a id=__codelineno-17-2 name=__codelineno-17-2 href=#__codelineno-17-2></a>Subject: Re: -d option not working. . .?
<a id=__codelineno-17-3 name=__codelineno-17-3 href=#__codelineno-17-3></a>Date: Wed, 12 Sep 2007 10:32:35 -0600
<a id=__codelineno-17-4 name=__codelineno-17-4 href=#__codelineno-17-4></a>To: bug-bash@gnu.org
<a id=__codelineno-17-5 name=__codelineno-17-5 href=#__codelineno-17-5></a>
<a id=__codelineno-17-6 name=__codelineno-17-6 href=#__codelineno-17-6></a>&gt; (QUOTED TEXT WAS REMOVED)
<a id=__codelineno-17-7 name=__codelineno-17-7 href=#__codelineno-17-7></a>
<a id=__codelineno-17-8 name=__codelineno-17-8 href=#__codelineno-17-8></a>The shell is first and foremost a way to launch other commands. The
<a id=__codelineno-17-9 name=__codelineno-17-9 href=#__codelineno-17-9></a>syntax is simply &quot;if&quot; followed by a command-list, (e.g. if /some/foo;
<a id=__codelineno-17-10 name=__codelineno-17-10 href=#__codelineno-17-10></a>or even if cmd1; cmd2; cmd3; then). Plus the &#39;( ... )&#39; syntax is
<a id=__codelineno-17-11 name=__codelineno-17-11 href=#__codelineno-17-11></a>already taken by the use of starting a subshell.
<a id=__codelineno-17-12 name=__codelineno-17-12 href=#__codelineno-17-12></a>
<a id=__codelineno-17-13 name=__codelineno-17-13 href=#__codelineno-17-13></a>As I recall in the original shell language the file test operator was
<a id=__codelineno-17-14 name=__codelineno-17-14 href=#__codelineno-17-14></a>not built-in. It was provided by the standalone &#39;/bin/test&#39; command.
<a id=__codelineno-17-15 name=__codelineno-17-15 href=#__codelineno-17-15></a>The result was effectively this:
<a id=__codelineno-17-16 name=__codelineno-17-16 href=#__codelineno-17-16></a>
<a id=__codelineno-17-17 name=__codelineno-17-17 href=#__codelineno-17-17></a> if /bin/test -d somedir
<a id=__codelineno-17-18 name=__codelineno-17-18 href=#__codelineno-17-18></a>
<a id=__codelineno-17-19 name=__codelineno-17-19 href=#__codelineno-17-19></a>Although the full path /bin/test was never used. I showed it that way
<a id=__codelineno-17-20 name=__codelineno-17-20 href=#__codelineno-17-20></a>here for emphasis that following the &#39;if&#39; statement is a command list.
<a id=__codelineno-17-21 name=__codelineno-17-21 href=#__codelineno-17-21></a>Normally it would simply have been:
<a id=__codelineno-17-22 name=__codelineno-17-22 href=#__codelineno-17-22></a>
<a id=__codelineno-17-23 name=__codelineno-17-23 href=#__codelineno-17-23></a> if test -d somedir
<a id=__codelineno-17-24 name=__codelineno-17-24 href=#__codelineno-17-24></a>
<a id=__codelineno-17-25 name=__codelineno-17-25 href=#__codelineno-17-25></a>Of course that is fine and for the best portability that style is
<a id=__codelineno-17-26 name=__codelineno-17-26 href=#__codelineno-17-26></a>still the recommended way today to use the test command. But many
<a id=__codelineno-17-27 name=__codelineno-17-27 href=#__codelineno-17-27></a>people find that it looks different from other programming languages.
<a id=__codelineno-17-28 name=__codelineno-17-28 href=#__codelineno-17-28></a>To make the test operator (note I mention the test operator and not
<a id=__codelineno-17-29 name=__codelineno-17-29 href=#__codelineno-17-29></a>the shell language, this is a localized change not affecting the
<a id=__codelineno-17-30 name=__codelineno-17-30 href=#__codelineno-17-30></a>language as a whole) look more like other programming languages the
<a id=__codelineno-17-31 name=__codelineno-17-31 href=#__codelineno-17-31></a>&#39;test&#39; program was coded to ignore the last argument if it was a &#39;]&#39;.
<a id=__codelineno-17-32 name=__codelineno-17-32 href=#__codelineno-17-32></a>Then a copy of the test program could be used as the &#39;[&#39; program.
<a id=__codelineno-17-33 name=__codelineno-17-33 href=#__codelineno-17-33></a>
<a id=__codelineno-17-34 name=__codelineno-17-34 href=#__codelineno-17-34></a> ...modify /bin/test to ignore &#39;]&#39; as last argument...
<a id=__codelineno-17-35 name=__codelineno-17-35 href=#__codelineno-17-35></a> cp /bin/test /bin/[
<a id=__codelineno-17-36 name=__codelineno-17-36 href=#__codelineno-17-36></a>
<a id=__codelineno-17-37 name=__codelineno-17-37 href=#__codelineno-17-37></a>This allows:
<a id=__codelineno-17-38 name=__codelineno-17-38 href=#__codelineno-17-38></a>
<a id=__codelineno-17-39 name=__codelineno-17-39 href=#__codelineno-17-39></a> if [ -d somedir ]
<a id=__codelineno-17-40 name=__codelineno-17-40 href=#__codelineno-17-40></a>
<a id=__codelineno-17-41 name=__codelineno-17-41 href=#__codelineno-17-41></a>Doesn&#39;t that look more normal? People liked it and it caught on. It
<a id=__codelineno-17-42 name=__codelineno-17-42 href=#__codelineno-17-42></a>was so popular that both &#39;test&#39; and &#39;[&#39; are now shell built-ins. They
<a id=__codelineno-17-43 name=__codelineno-17-43 href=#__codelineno-17-43></a>don&#39;t launch an external &#39;/bin/test&#39; program anymore. But they *used*
<a id=__codelineno-17-44 name=__codelineno-17-44 href=#__codelineno-17-44></a>to launch external programs. Therefore argument parsing is the same
<a id=__codelineno-17-45 name=__codelineno-17-45 href=#__codelineno-17-45></a>as if they still did launch an external program. This affects
<a id=__codelineno-17-46 name=__codelineno-17-46 href=#__codelineno-17-46></a>argument parsing.
<a id=__codelineno-17-47 name=__codelineno-17-47 href=#__codelineno-17-47></a>
<a id=__codelineno-17-48 name=__codelineno-17-48 href=#__codelineno-17-48></a> it test -f *.txt
<a id=__codelineno-17-49 name=__codelineno-17-49 href=#__codelineno-17-49></a> test: too many arguments
<a id=__codelineno-17-50 name=__codelineno-17-50 href=#__codelineno-17-50></a>
<a id=__codelineno-17-51 name=__codelineno-17-51 href=#__codelineno-17-51></a>Oops. I have twenty .txt files and so test got one -f followed by the
<a id=__codelineno-17-52 name=__codelineno-17-52 href=#__codelineno-17-52></a>first file followed by the remaining files. (e.g. test -f 1.txt 2.txt
<a id=__codelineno-17-53 name=__codelineno-17-53 href=#__codelineno-17-53></a>3.txt 4.txt)
<a id=__codelineno-17-54 name=__codelineno-17-54 href=#__codelineno-17-54></a>
<a id=__codelineno-17-55 name=__codelineno-17-55 href=#__codelineno-17-55></a> if test -d $file
<a id=__codelineno-17-56 name=__codelineno-17-56 href=#__codelineno-17-56></a> test: argument expected
<a id=__codelineno-17-57 name=__codelineno-17-57 href=#__codelineno-17-57></a>
<a id=__codelineno-17-58 name=__codelineno-17-58 href=#__codelineno-17-58></a>Oops. I meant to set file.
<a id=__codelineno-17-59 name=__codelineno-17-59 href=#__codelineno-17-59></a>
<a id=__codelineno-17-60 name=__codelineno-17-60 href=#__codelineno-17-60></a> file=/path/some/file
<a id=__codelineno-17-61 name=__codelineno-17-61 href=#__codelineno-17-61></a> if test -d $file
<a id=__codelineno-17-62 name=__codelineno-17-62 href=#__codelineno-17-62></a>
<a id=__codelineno-17-63 name=__codelineno-17-63 href=#__codelineno-17-63></a>If variables such as that are not set then they wlll be expanded by
<a id=__codelineno-17-64 name=__codelineno-17-64 href=#__codelineno-17-64></a>the shell before passing them to the (possibly external) command and
<a id=__codelineno-17-65 name=__codelineno-17-65 href=#__codelineno-17-65></a>disappear entirely. This is why test arguments should always be quoted.
<a id=__codelineno-17-66 name=__codelineno-17-66 href=#__codelineno-17-66></a>
<a id=__codelineno-17-67 name=__codelineno-17-67 href=#__codelineno-17-67></a> if test -d &quot;$file&quot;
<a id=__codelineno-17-68 name=__codelineno-17-68 href=#__codelineno-17-68></a> if [ -d &quot;$file&quot; ]
<a id=__codelineno-17-69 name=__codelineno-17-69 href=#__codelineno-17-69></a>
<a id=__codelineno-17-70 name=__codelineno-17-70 href=#__codelineno-17-70></a>Actually today test is defined that if only one argument is given as
<a id=__codelineno-17-71 name=__codelineno-17-71 href=#__codelineno-17-71></a>in this case &quot;test FOO&quot; then then test returns true if the argument is
<a id=__codelineno-17-72 name=__codelineno-17-72 href=#__codelineno-17-72></a>non-zero in text length. Because &quot;-d&quot; is non-zero length &quot;test -d&quot; is
<a id=__codelineno-17-73 name=__codelineno-17-73 href=#__codelineno-17-73></a>true. The number of arguments affects how test parses the args. This
<a id=__codelineno-17-74 name=__codelineno-17-74 href=#__codelineno-17-74></a>avoids a case where depending upon the data may look like a test
<a id=__codelineno-17-75 name=__codelineno-17-75 href=#__codelineno-17-75></a>operator.
<a id=__codelineno-17-76 name=__codelineno-17-76 href=#__codelineno-17-76></a>
<a id=__codelineno-17-77 name=__codelineno-17-77 href=#__codelineno-17-77></a> DATA=&quot;something&quot;
<a id=__codelineno-17-78 name=__codelineno-17-78 href=#__codelineno-17-78></a> if test &quot;$DATA&quot; # true, $DATA is non-zero length
<a id=__codelineno-17-79 name=__codelineno-17-79 href=#__codelineno-17-79></a>
<a id=__codelineno-17-80 name=__codelineno-17-80 href=#__codelineno-17-80></a> DATA=&quot;&quot;
<a id=__codelineno-17-81 name=__codelineno-17-81 href=#__codelineno-17-81></a> if test &quot;$DATA&quot; # false, $DATA is zero length
<a id=__codelineno-17-82 name=__codelineno-17-82 href=#__codelineno-17-82></a>
<a id=__codelineno-17-83 name=__codelineno-17-83 href=#__codelineno-17-83></a>But the problem case is how should test handle an argument that looks
<a id=__codelineno-17-84 name=__codelineno-17-84 href=#__codelineno-17-84></a>like an operator? This used to generate errors but now because it is
<a id=__codelineno-17-85 name=__codelineno-17-85 href=#__codelineno-17-85></a>only one argument is defined to be the same as test -n $DATA.
<a id=__codelineno-17-86 name=__codelineno-17-86 href=#__codelineno-17-86></a>
<a id=__codelineno-17-87 name=__codelineno-17-87 href=#__codelineno-17-87></a> DATA=&quot;-d&quot;
<a id=__codelineno-17-88 name=__codelineno-17-88 href=#__codelineno-17-88></a> if test &quot;$DATA&quot; # true, $DATA is non-zero length
<a id=__codelineno-17-89 name=__codelineno-17-89 href=#__codelineno-17-89></a> if test -d # true, same as previous case.
<a id=__codelineno-17-90 name=__codelineno-17-90 href=#__codelineno-17-90></a>
<a id=__codelineno-17-91 name=__codelineno-17-91 href=#__codelineno-17-91></a>Because test and [ are possibly external commands all of the parts of
<a id=__codelineno-17-92 name=__codelineno-17-92 href=#__codelineno-17-92></a>them are chosen to avoid shell metacharacters. The Fortran operator
<a id=__codelineno-17-93 name=__codelineno-17-93 href=#__codelineno-17-93></a>naming was well known at the time (e.g. .gt., .eq., etc.) and was
<a id=__codelineno-17-94 name=__codelineno-17-94 href=#__codelineno-17-94></a>pressed into service for the shell test operator too. Comming from
<a id=__codelineno-17-95 name=__codelineno-17-95 href=#__codelineno-17-95></a>Fortran using -gt, -eq, etc. looked very normal.
<a id=__codelineno-17-96 name=__codelineno-17-96 href=#__codelineno-17-96></a>
<a id=__codelineno-17-97 name=__codelineno-17-97 href=#__codelineno-17-97></a>Incorrect use generating unlikely to be intended results:
<a id=__codelineno-17-98 name=__codelineno-17-98 href=#__codelineno-17-98></a>
<a id=__codelineno-17-99 name=__codelineno-17-99 href=#__codelineno-17-99></a> if test 5 &gt; 2 # true, &quot;5&quot; is non-zero length, creates file named &quot;2&quot;
<a id=__codelineno-17-100 name=__codelineno-17-100 href=#__codelineno-17-100></a>
<a id=__codelineno-17-101 name=__codelineno-17-101 href=#__codelineno-17-101></a>Intended use:
<a id=__codelineno-17-102 name=__codelineno-17-102 href=#__codelineno-17-102></a>
<a id=__codelineno-17-103 name=__codelineno-17-103 href=#__codelineno-17-103></a> if test 5 -gt 2 # true (and no shell meta characters needing quoting)
<a id=__codelineno-17-104 name=__codelineno-17-104 href=#__codelineno-17-104></a>
<a id=__codelineno-17-105 name=__codelineno-17-105 href=#__codelineno-17-105></a>Then much later, sometime in the mid 1980&#39;s, the Korn sh decided to
<a id=__codelineno-17-106 name=__codelineno-17-106 href=#__codelineno-17-106></a>improve upon this situation. A new test operator was introduced.
<a id=__codelineno-17-107 name=__codelineno-17-107 href=#__codelineno-17-107></a>This one was always a shell built-in and therefore could act upon the
<a id=__codelineno-17-108 name=__codelineno-17-108 href=#__codelineno-17-108></a>shell arguments directly. This is &#39;[[&#39; which is a shell keyword.
<a id=__codelineno-17-109 name=__codelineno-17-109 href=#__codelineno-17-109></a>(Keyword, metacharacters, builtins, all are different.) Because the
<a id=__codelineno-17-110 name=__codelineno-17-110 href=#__codelineno-17-110></a>shell processes [[ internally all arguments are known and do not need
<a id=__codelineno-17-111 name=__codelineno-17-111 href=#__codelineno-17-111></a>to be quoted.
<a id=__codelineno-17-112 name=__codelineno-17-112 href=#__codelineno-17-112></a>
<a id=__codelineno-17-113 name=__codelineno-17-113 href=#__codelineno-17-113></a> if [[ -d $file ]] # okay
<a id=__codelineno-17-114 name=__codelineno-17-114 href=#__codelineno-17-114></a> if [[ 5 &gt; 2 ]] # okay
<a id=__codelineno-17-115 name=__codelineno-17-115 href=#__codelineno-17-115></a>
<a id=__codelineno-17-116 name=__codelineno-17-116 href=#__codelineno-17-116></a>I am sure that I am remembering a detail wrong but hopefully this is
<a id=__codelineno-17-117 name=__codelineno-17-117 href=#__codelineno-17-117></a>useful as a gentle introduction and interesting anyway.
<a id=__codelineno-17-118 name=__codelineno-17-118 href=#__codelineno-17-118></a>
<a id=__codelineno-17-119 name=__codelineno-17-119 href=#__codelineno-17-119></a>Bob
</code></pre></div> <p>I hope this text protects you a bit from stepping from one pitfall into the next.</p> <p>I find it very interesting and informative, that's why I quoted it here. Many thanks, Bob, also for the permission to copy the text here!</p> <h2 id=code-examples>Code examples<a class=headerlink href=#code-examples title="Permanent link">&para;</a></h2> <h3 id=snipplets>Snipplets<a class=headerlink href=#snipplets title="Permanent link">&para;</a></h3> <p>Some code snipplets follow, different ways of shell reaction is used.</p> <ul> <li><strong>check if a variable is defined/non-NULL</strong><ul> <li><code>test "$MYVAR"</code></li> <li><code>[ "$MYVAR" ]</code></li> <li><strong>Note:</strong> There are possibilities to make a difference if a variable is <em>undefined</em> or <em>NULL</em> - see <a href=../../syntax/pe/#use_an_alternate_value>Parameter Expansion - Using an alternate value</a></li> </ul> </li> <li><strong>check if a directory exists, if not, create it</strong><ul> <li><code>test ! -d /home/user/foo &amp;&amp; mkdir /home/user/foo</code></li> <li><code>[ ! -d /home/user/foo ] &amp;&amp; mkdir /home/user/foo</code></li> <li><code>if [ ! -d /home/user/foo ]; then mkdir /home/user/foo; fi</code></li> </ul> </li> <li><strong>check if minimum one parameter was given, and that one is "Hello"</strong><ul> <li><code>test $# -ge 1 -a "$1" = "Hello" || exit 1</code></li> <li><code>[ $# -ge 1 ] &amp;&amp; [ "$1" = "Hello" ] || exit 1</code> (see <a href=../../syntax/basicgrammar/#lists>lists description</a>)</li> </ul> </li> </ul> <h3 id=listing-directories>Listing directories<a class=headerlink href=#listing-directories title="Permanent link">&para;</a></h3> <p>Using a <a href=../../syntax/ccmd/classic_for/ >for-loop</a> to iterate through all entries of a directory, if an entry is a directory (<code>[ -d "$fn" ]</code>), print its name:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-18-1 name=__codelineno-18-1 href=#__codelineno-18-1></a><span class=k>for</span><span class=w> </span>fn<span class=w> </span><span class=k>in</span><span class=w> </span>*<span class=p>;</span><span class=w> </span><span class=k>do</span>
<a id=__codelineno-18-2 name=__codelineno-18-2 href=#__codelineno-18-2></a><span class=w> </span><span class=o>[</span><span class=w> </span>-d<span class=w> </span><span class=s2>&quot;</span><span class=nv>$fn</span><span class=s2>&quot;</span><span class=w> </span><span class=o>]</span><span class=w> </span><span class=o>&amp;&amp;</span><span class=w> </span><span class=nb>echo</span><span class=w> </span><span class=s2>&quot;</span><span class=nv>$fn</span><span class=s2>&quot;</span>
<a id=__codelineno-18-3 name=__codelineno-18-3 href=#__codelineno-18-3></a><span class=k>done</span>
</code></pre></div> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li>Internal: <a href=../../syntax/ccmd/conditional_expression/ >conditional expression</a> (aka "the new test command")</li> <li>Internal: <a href=../../syntax/ccmd/if_clause/ >the if-clause</a></li> </ul> <div class=footnote> <hr> <ol> <li id=fn:1> <p><rant>Of course, one can wonder what is the use of including the parenthesis in the specification without defining the behaviour with more than 4 arguments or how usefull are the examples with 7 or 9 arguments attached to the specification.</rant>&#160;<a class=footnote-backref href=#fnref:1 title="Jump back to footnote 1 in the text">&#8617;</a></p> </li> </ol> </div> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Created> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> </aside> <h2 id=__comments>Comments</h2> <script src=https://giscus.app/client.js data-repo=flokoe/bash-hackers-wiki data-repo-id=R_kgDOJ3Nr6Q data-category="Giscus Page Comments" data-category-id=DIC_kwDOJ3Nr6c4CXq9t data-mapping=pathname data-strict=1 data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=en data-loading=lazy crossorigin=anonymous async>
</script> <script>
var giscus = document.querySelector("script[src*=giscus]")
/* Set palette on initial load */
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
giscus.setAttribute("data-theme", theme)
}
/* Register event handlers after documented loaded */
document.addEventListener("DOMContentLoaded", function() {
var ref = document.querySelector("[data-md-component=palette]")
ref.addEventListener("change", function() {
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
/* Instruct Giscus to change theme */
var frame = document.querySelector(".giscus-frame")
frame.contentWindow.postMessage(
{ giscus: { setConfig: { theme } } },
"https://giscus.app"
)
}
})
})
</script> </article> </div> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <script id=__config type=application/json>{"base": "../..", "features": ["navigation.instant", "navigation.tracking", "navigation.tabs", "navigation.sections", "navigation.top", "content.action.view", "content.action.edit", "search.suggest", "search.highlight", "content.code.copy"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script> <script src=../../assets/javascripts/bundle.83f73b43.min.js></script> </body> </html>