{"id":20399,"date":"2018-02-01T14:34:40","date_gmt":"2018-02-01T19:34:40","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=20399"},"modified":"2018-02-05T14:53:18","modified_gmt":"2018-02-05T19:53:18","slug":"things-i-wish-id-known-about-bash","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2018\/02\/01\/things-i-wish-id-known-about-bash\/","title":{"rendered":"Things I Wish I&rsquo;d Known About Bash"},"content":{"rendered":"<p><a href=\"https:\/\/zwischenzugs.com\/2018\/01\/06\/ten-things-i-wish-id-known-about-bash\/\">zwischenzugs<\/a> (via <a href=\"https:\/\/news.ycombinator.com\/item?id=16084763\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/zwischenzugs.com\/2018\/01\/06\/ten-things-i-wish-id-known-about-bash\/\"><p>The difference between <code>[<\/code>&nbsp;and <code>[[<\/code>&nbsp;was another thing I never really understood. <code>[<\/code>&nbsp;is the original form for tests, and then <code>[[<\/code>&nbsp;was introduced, which is more flexible and intuitive. In the first <code>if<\/code> block above, the if statement barfs because the <code>$(grep not_there \/dev\/null)<\/code>&nbsp;is evaluated to nothing, resulting in this comparison:<\/p>\n<p><code>[ = '' ]<\/code><\/p>\n<p>which makes no sense. The double bracket form handles this for you.<\/p>\n<p>This is why you occasionally see comparisons like this in bash scripts:<\/p>\n<p><code>if [ x$(grep not_there \/dev\/null) = 'x' ]<\/code><\/p>\n<p>so that if the command returns nothing it still runs. There&rsquo;s no need for it, but that&rsquo;s why it exists.<\/p>\n<p>[&#8230;]<\/p>\n<p>Bash has configurable options which can be set on the fly. I use two of these all the time:<\/p>\n<pre>set -e<\/pre>\n<p>exits from a script if any command returned a non-zero exit code (see above).<\/p>\n<p>This outputs the commands that get run as they run:<\/p>\n<pre>set -x<\/pre>\n<\/blockquote>\n\n<p><a href=\"https:\/\/zwischenzugs.com\/2018\/01\/21\/ten-more-things-i-wish-id-known-about-bash\/\">zwischenzugs<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=16198974\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/zwischenzugs.com\/2018\/01\/21\/ten-more-things-i-wish-id-known-about-bash\/\"><ul>\n<li>The <code>#<\/code>&nbsp;means &lsquo;match and remove the following pattern from the start of the string&rsquo;<\/li>\n<li>The <code>%<\/code>&nbsp;means &lsquo;match and remove the following pattern from the end of the string<\/li>\n<\/ul>\n<p>[&#8230;]<\/p>\n<p>The <code>trap<\/code>&nbsp;builtin can be used to &lsquo;catch&rsquo; when a <a href=\"http:\/\/man7.org\/linux\/man-pages\/man7\/signal.7.html\">signal<\/a> is sent to your script.<\/p>\n<\/blockquote>\n\n<p>Previously: <a href=\"https:\/\/mjtsai.com\/blog\/2016\/09\/26\/mac-terminal-tips\/\">Mac Terminal Tips<\/a>, <a href=\"http:\/\/furbo.org\/2014\/09\/03\/the-terminal\/\">Craig&rsquo;s Terminal Tips<\/a>.<\/p>\n\n<p>Update (2018-02-05): <a href=\"https:\/\/twitter.com\/teilweise\/status\/959717286847418370\">Der Teilweise<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/teilweise\/status\/959717286847418370\">\n<p>\nIt&rsquo;s wrong regading <code>!$<\/code>:\n<\/p>\n\n<p>\n<code>!$<\/code> is <em>not<\/em> the last argument of the previous command. It&rsquo;s the last word. The last argument is <code>$_<\/code>.\n<\/p>\n\n<p>\nGiven <code>echo x&gt;\/dev\/null<\/code>:\n<\/p>\n\n<p>\n<code>$_<\/code> is <code>x<\/code>\n<\/p>\n\n<p>\n<code>!$<\/code> is <code>\/dev\/null<\/code>\n<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>zwischenzugs (via Hacker News): The difference between [&nbsp;and [[&nbsp;was another thing I never really understood. [&nbsp;is the original form for tests, and then [[&nbsp;was introduced, which is more flexible and intuitive. In the first if block above, the if statement barfs because the $(grep not_there \/dev\/null)&nbsp;is evaluated to nothing, resulting in this comparison: [ = [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[],"tags":[767,30,1529,318,163],"class_list":["post-20399","post","type-post","status-publish","format-standard","hentry","tag-bash","tag-mac","tag-macos-10-13","tag-terminal","tag-unix"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20399","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=20399"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20399\/revisions"}],"predecessor-version":[{"id":20417,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20399\/revisions\/20417"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=20399"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=20399"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=20399"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}