[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"sanity-CyDT8JJESshxCSpWY3DapjkwDkcWdU1il0sF0WQxva4":3,"sanity-eonwX9ESNRvpIqnoUgF6L9sK8-WufIhYsm1CG1RfK08":1190},{"data":4,"sourceMap":-1},{"latestPodcast":5,"latestReleases":14,"post":39,"recent":1165},[6],{"_id":7,"publishedAt":8,"slug":9,"sponsored":12,"title":13},"7ebd76d2-cebc-4b88-82f9-3dfb2c8bc5ca","2026-07-08T04:40:00.000Z",{"_type":10,"current":11},"slug","what-s-left-for-infrastructure-as-code-after-ai-moves-in",true,"What's left for infrastructure-as-code after AI moves in?",[15,21,27,33],{"_id":16,"publishedAt":17,"slug":18,"title":20},"eb5b66eb-9410-4329-83bb-22bbff39402a","2026-04-28T13:00:00.000Z",{"_type":10,"current":19},"turn-scattered-knowledge-into-trusted-intelligence","Turning scattered knowledge into trusted intelligence: Stack Internal 2026.3",{"_id":22,"publishedAt":23,"slug":24,"title":26},"369c2401-b62e-4a37-8ff8-bf603023ecad","2026-03-02T15:03:00.988Z",{"_type":10,"current":25},"what-s-new-at-stack-overflow-march-2026","What’s new at Stack Overflow: March 2026",{"_id":28,"publishedAt":29,"slug":30,"title":32},"5e9053a4-07ea-447c-91ea-29e0b6228537","2026-02-02T15:00:00.000Z",{"_type":10,"current":31},"what-s-new-at-stack-overflow-february-2026","What’s new at Stack Overflow: February 2026",{"_id":34,"publishedAt":35,"slug":36,"title":38},"a1b538eb-a8a6-46d0-80a1-ac70ec9bb935","2026-01-05T10:00:00.000-05:00",{"_type":10,"current":37},"what-s-new-at-stack-overflow-january-2026","What’s new at Stack Overflow: January 2026",{"_createdAt":40,"_id":41,"_rev":42,"_type":43,"_updatedAt":44,"author":45,"body":57,"comments":12,"dateUrl":1116,"excerpt":1117,"image":1118,"legacyBody":1122,"product":85,"publishedAt":1125,"slug":1126,"sponsored":85,"tags":1128,"title":1164,"visible":12},"2023-05-25T09:39:13Z","wp-post-15039","07ZbrKPSUrjrV4wQ6fIhWF","blogPost","2023-07-13T14:55:31Z",[46],{"_createdAt":47,"_id":48,"_rev":49,"_type":50,"_updatedAt":47,"avatar":51,"employee":53,"name":54,"slug":55},"2023-05-23T16:27:18Z","wp-author-268","9HpbCsT2tq0xwozQfkcuVr","blogAuthor",{"_type":52},"image","none","Breanne Boland",{"current":56},"bboland",[58,69,86,95,120,149,183,191,199,238,246,299,307,329,341,357,365,373,407,469,477,485,493,517,536,555,571,613,686,771,779,787,814,822,844,921,944,952,960,1016,1024,1038,1085,1093,1101],{"_key":59,"_type":60,"children":61,"markDefs":67,"style":68},"87bb580eb59c","block",[62],{"_key":63,"_type":64,"marks":65,"text":66},"87bb580eb59c0","span",[],"A terminal is never just a terminal. An elaborate prompt can mean someone digs deeply into optimizing the tools she uses, while the information it contains can give you an idea of what kind of engineering she’s done. What you type into the command line can tell you about environment variables, hidden configs, and OS defaults you never knew about. You can make it speak shorthand only known to your terminal and you. And all of it can help you work more efficiently and effectively.",[],"normal",{"_key":70,"_type":60,"children":71,"markDefs":81,"style":68},"03a382150fe2",[72,77],{"_key":73,"_type":64,"marks":74,"text":76},"03a382150fe20",[75],"07125ae637ec","Bash",{"_key":78,"_type":64,"marks":79,"text":80},"03a382150fe21",[]," (a term used for both the Unix shell and the command language; I’ll be using the second meaning in this post) is usually a skill mentioned only in job descriptions for site reliability engineers and other ops jobs. Those same job posts often ask for automation skills, which is a positive way of asking for someone who’s professionally lazy in a way that results in efficiency. The good news is that developers can also learn a few tricks from the land of ops to make their days easier and their work better.",[82],{"_key":75,"_type":83,"href":84,"reference":85},"link","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBash_(Unix_shell)",null,{"_key":87,"_type":60,"children":88,"markDefs":93,"style":94},"016710f9f6b6",[89],{"_key":90,"_type":64,"marks":91,"text":92},"016710f9f6b60",[],"Your own personal(ized) terminal",[],"h2",{"_key":96,"_type":60,"children":97,"markDefs":119,"style":68},"6ca23f4b7de7",[98,102,107,111,115],{"_key":99,"_type":64,"marks":100,"text":101},"6ca23f4b7de70",[],"There are lots of ways to customize your command line prompt and terminal to make you more efficient at work. We’ll start with possibly the most powerful one: meet ",{"_key":103,"_type":64,"marks":104,"text":106},"6ca23f4b7de71",[105],"code","~\u002F.bashrc",{"_key":108,"_type":64,"marks":109,"text":110},"6ca23f4b7de72",[]," and ",{"_key":112,"_type":64,"marks":113,"text":114},"6ca23f4b7de73",[105],"~\u002F.bash_profile",{"_key":116,"_type":64,"marks":117,"text":118},"6ca23f4b7de74",[],".",[],{"_key":121,"_type":60,"children":122,"markDefs":144,"style":68},"5dc0cd795391",[123,127,132,136,140],{"_key":124,"_type":64,"marks":125,"text":126},"5dc0cd7953910",[],"This file exists under several different names, depending on your OS and what you’re trying to accomplish, and it can hold a lot of things that can make your life easier: shorter aliases for common commands, your custom ",{"_key":128,"_type":64,"marks":129,"text":131},"5dc0cd7953911",[130],"cfa4491c6256","PATH",{"_key":133,"_type":64,"marks":134,"text":135},"5dc0cd7953912",[],", Bash functions to populate your prompt with environment information, history length, command line completion, default editors, and more. With a little observation of your terminal habits (and a little knowledge of ",{"_key":137,"_type":64,"marks":138,"text":76},"5dc0cd7953913",[139],"c9e23e76ef44",{"_key":141,"_type":64,"marks":142,"text":143},"5dc0cd7953914",[],", the command language used in many terminals), you can put all kinds of things in here that will make your life easier.",[145,147],{"_key":130,"_type":83,"href":146,"reference":85},"http:\u002F\u002Fwww.linfo.org\u002Fpath_env_var.html",{"_key":139,"_type":83,"href":148,"reference":85},"http:\u002F\u002Ftldp.org\u002FHOWTO\u002FBash-Prog-Intro-HOWTO.html",{"_key":150,"_type":60,"children":151,"markDefs":180,"style":68},"a704a35c25c7",[152,156,161,165,168,172,176],{"_key":153,"_type":64,"marks":154,"text":155},"a704a35c25c70",[],"Which file you use depends on your OS. ",{"_key":157,"_type":64,"marks":158,"text":160},"a704a35c25c71",[159],"494f33989069","This post",{"_key":162,"_type":64,"marks":163,"text":164},"a704a35c25c72",[]," gives a rundown on the purposes and tradeoffs of the two files. If you use a Mac, though, use ",{"_key":166,"_type":64,"marks":167,"text":114},"a704a35c25c73",[105],{"_key":169,"_type":64,"marks":170,"text":171},"a704a35c25c74",[],". Run ",{"_key":173,"_type":64,"marks":174,"text":175},"a704a35c25c75",[105],"source ~\u002F.bash_profile",{"_key":177,"_type":64,"marks":178,"text":179},"a704a35c25c76",[]," once you’ve saved your changes, so they’re live in your terminal (or just close your terminal window and open a new one).",[181],{"_key":159,"_type":83,"href":182,"reference":85},"http:\u002F\u002Fwww.joshstaiger.org\u002Farchives\u002F2005\u002F07\u002Fbash_profile_vs.html",{"_key":184,"_type":60,"children":185,"markDefs":190,"style":68},"1f3e85dcc760",[186],{"_key":187,"_type":64,"marks":188,"text":189},"1f3e85dcc7600",[],"What else should you put in your beautifully customized new file? Let’s start with aliases.",[],{"_key":192,"_type":60,"children":193,"markDefs":198,"style":68},"0fdd246107e5",[194],{"_key":195,"_type":64,"marks":196,"text":197},"0fdd246107e50",[],"When automating things in ops work, I watch what operations I do more than a couple of times, make notes on what I did, and put those on a list of likely script ideas. Once it’s clear I’ll be doing it again and again, I know it’s worth the time to put a solution into code. You can do the same thing with your own habits. What commands are you typing all the time? What values are you frequently using? These can all be aliases.",[],{"_key":200,"_type":60,"children":201,"markDefs":237,"style":68},"030d8434f7bc",[202,206,210,213,217,221,225,229,233],{"_key":203,"_type":64,"marks":204,"text":205},"030d8434f7bc0",[],"For example, ",{"_key":207,"_type":64,"marks":208,"text":209},"030d8434f7bc1",[105],"git commit",{"_key":211,"_type":64,"marks":212,"text":110},"030d8434f7bc2",[],{"_key":214,"_type":64,"marks":215,"text":216},"030d8434f7bc3",[105],"git checkout",{"_key":218,"_type":64,"marks":219,"text":220},"030d8434f7bc4",[]," can become ",{"_key":222,"_type":64,"marks":223,"text":224},"030d8434f7bc5",[105],"gc ",{"_key":226,"_type":64,"marks":227,"text":228},"030d8434f7bc6",[],"and ",{"_key":230,"_type":64,"marks":231,"text":232},"030d8434f7bc7",[105],"gco ",{"_key":234,"_type":64,"marks":235,"text":236},"030d8434f7bc8",[],"(or whatever matches your mental map of abbreviations). But you can go further than that by aliasing long commands with lots of flags and arguments. Here’s how to make one:",[],{"_key":239,"_type":60,"children":240,"markDefs":245,"style":68},"96d4f044e13a",[241],{"_key":242,"_type":64,"marks":243,"text":244},"96d4f044e13a0",[105],"alias $preferredAlias='$commandToAlias'",[],{"_key":247,"_type":60,"children":248,"markDefs":298,"style":68},"687b311a7224",[249,253,257,261,265,269,273,277,281,286,290,294],{"_key":250,"_type":64,"marks":251,"text":252},"687b311a72240",[105],"alias",{"_key":254,"_type":64,"marks":255,"text":256},"687b311a72241",[]," is the Bash command here (you can make an alias directly on the command line too, and it will only be available for that session until you close that terminal). ",{"_key":258,"_type":64,"marks":259,"text":260},"687b311a72242",[105],"$preferredAlias",{"_key":262,"_type":64,"marks":263,"text":264},"687b311a72243",[]," is your nice, short name for ",{"_key":266,"_type":64,"marks":267,"text":268},"687b311a72244",[105],"$commandToAlias",{"_key":270,"_type":64,"marks":271,"text":272},"687b311a72245",[],", the longer, more cumbersome command you’re typing all the time. No spaces around the ",{"_key":274,"_type":64,"marks":275,"text":276},"687b311a72246",[105],"= ",{"_key":278,"_type":64,"marks":279,"text":280},"687b311a72247",[],"and don’t forget the single ",{"_key":282,"_type":64,"marks":283,"text":285},"687b311a72248",[284],"em","straight",{"_key":287,"_type":64,"marks":288,"text":289},"687b311a72249",[]," quotes around the command you’re aliasing. You can also chain commands together using ",{"_key":291,"_type":64,"marks":292,"text":293},"687b311a722410",[105],"&&",{"_key":295,"_type":64,"marks":296,"text":297},"687b311a722411",[],". Ever sat next to someone whose command line navigation was completely opaque because they’d optimized their work into a flurry of short aliases? Now you can be that person, too.",[],{"_key":300,"_type":60,"children":301,"markDefs":306,"style":68},"1ce458126b02",[302],{"_key":303,"_type":64,"marks":304,"text":305},"1ce458126b020",[],"Here are a couple I use:",[],{"_key":308,"_type":60,"children":309,"level":326,"listItem":327,"markDefs":328,"style":68},"2e2f3139b6cd",[310,314,318,322],{"_key":311,"_type":64,"marks":312,"text":313},"2e2f3139b6cd0",[105],"mkcd='mkdir $1 && cd $1'",{"_key":315,"_type":64,"marks":316,"text":317},"2e2f3139b6cd1",[]," (consolidating a common pair of operations; the $1 takes the first argument, in this case the new file you want to ",{"_key":319,"_type":64,"marks":320,"text":321},"2e2f3139b6cd2",[105],"cd",{"_key":323,"_type":64,"marks":324,"text":325},"2e2f3139b6cd3",[]," into)",1,"bullet",[],{"_key":330,"_type":60,"children":331,"level":326,"listItem":327,"markDefs":340,"style":68},"e1d9bb980b9d",[332,336],{"_key":333,"_type":64,"marks":334,"text":335},"e1d9bb980b9d0",[105],"tfplan='terraform init && terraform plan'",{"_key":337,"_type":64,"marks":338,"text":339},"e1d9bb980b9d1",[]," (preventing a common mistake for me; this can be used to chain any two commonly paired commands)",[],{"_key":342,"_type":60,"children":343,"markDefs":356,"style":68},"f9fa67cbbdee",[344,348,352],{"_key":345,"_type":64,"marks":346,"text":347},"f9fa67cbbdee0",[],"If you frequently work across different OSes (varying flavors of Linux, Mac OS), you can go a little further by creating multiple tailored dotfiles that assign slightly differing commands that achieve the same thing to the same alias. No more remembering the minute differences that only come up every month or two—it’s the same couple of characters wherever you are. If you’re prone to misspelling commands (looking at you, ",{"_key":349,"_type":64,"marks":350,"text":351},"f9fa67cbbdee1",[105],"gerp",{"_key":353,"_type":64,"marks":354,"text":355},"f9fa67cbbdee2",[],"), you can alias those too.",[],{"_key":358,"_type":60,"children":359,"markDefs":364,"style":68},"8b9688eb2e98",[360],{"_key":361,"_type":64,"marks":362,"text":363},"8b9688eb2e980",[],"Now let’s look at another capability of dotfiles: customizing your prompt.",[],{"_key":366,"_type":60,"children":367,"markDefs":372,"style":94},"ae7464f0ce5b",[368],{"_key":369,"_type":64,"marks":370,"text":371},"ae7464f0ce5b0",[],"A constant source of truth on the command line",[],{"_key":374,"_type":60,"children":375,"markDefs":404,"style":68},"3b99e29aa0c5",[376,380,384,388,393,397,400],{"_key":377,"_type":64,"marks":378,"text":379},"3b99e29aa0c50",[],"Your terminal prompt is one of the places you can be kindest to yourself, putting what you need in there so you don’t have to type ",{"_key":381,"_type":64,"marks":382,"text":383},"3b99e29aa0c51",[105],"pwd",{"_key":385,"_type":64,"marks":386,"text":387},"3b99e29aa0c52",[]," all the time or wonder exactly how long ago you typed that fateful command. At a minimum, I suggest adding a timestamp with minutes to it; that way, if you need to backtrack through recent work to tie cause to effect, you can precisely anchor an action’s time with minimal work. Beyond that, I also suggest adding your working directory and current git branch. My go-to tool for setting this up inexpensively is ",{"_key":389,"_type":64,"marks":390,"text":392},"3b99e29aa0c53",[391],"207ed3f05e4a","EzPrompt",{"_key":394,"_type":64,"marks":395,"text":396},"3b99e29aa0c54",[],", which lets you drag and drop your desired prompt elements and returns the Bash you need to add to ",{"_key":398,"_type":64,"marks":399,"text":114},"3b99e29aa0c55",[105],{"_key":401,"_type":64,"marks":402,"text":403},"3b99e29aa0c56",[],". It’s a good, simple start when you’re first cultivating your dotfiles.",[405],{"_key":391,"_type":83,"href":406,"reference":85},"http:\u002F\u002Fezprompt.net\u002F",{"_key":408,"_type":60,"children":409,"markDefs":458,"style":68},"b3bde2d183e5",[410,414,419,423,428,431,436,440,445,449,454],{"_key":411,"_type":64,"marks":412,"text":413},"b3bde2d183e50",[],"If you want to get a little more involved, you can try something like ",{"_key":415,"_type":64,"marks":416,"text":418},"b3bde2d183e51",[417],"743d82f7dfb8","Powerline",{"_key":420,"_type":64,"marks":421,"text":422},"b3bde2d183e52",[],", which looks slick and offers more involved status information. And if you want to roll your own, self-educate about ",{"_key":424,"_type":64,"marks":425,"text":427},"b3bde2d183e53",[426],"8d9f08715c4c","how to work with colors in the terminal",{"_key":429,"_type":64,"marks":430,"text":110},"b3bde2d183e54",[],{"_key":432,"_type":64,"marks":433,"text":435},"b3bde2d183e55",[434],"7922083e09ab","the elements you can add to your prompt",{"_key":437,"_type":64,"marks":438,"text":439},"b3bde2d183e56",[],". There’s a whole galaxy of options out there, and ",{"_key":441,"_type":64,"marks":442,"text":444},"b3bde2d183e57",[443],"549b8a041ee4","Terminals Are Sexy",{"_key":446,"_type":64,"marks":447,"text":448},"b3bde2d183e58",[]," provides guidance to some of the constellations you can explore. Hand-crafted customization is a great way to get used to Bash syntax. If you’re looking to do something more complex with a lengthier command, ",{"_key":450,"_type":64,"marks":451,"text":453},"b3bde2d183e59",[452],"be0117b42b37","Pipeline",{"_key":455,"_type":64,"marks":456,"text":457},"b3bde2d183e510",[]," provides an interactive environment to help you refine your output, showing you what your command produces as you edit it.",[459,461,463,465,467],{"_key":417,"_type":83,"href":460,"reference":85},"https:\u002F\u002Fgithub.com\u002Fpowerline\u002Fpowerline",{"_key":426,"_type":83,"href":462,"reference":85},"http:\u002F\u002Fwww.marinamele.com\u002F2014\u002F05\u002Fcustomize-colors-of-your-terminal-in-mac-os-x.html",{"_key":434,"_type":83,"href":464,"reference":85},"https:\u002F\u002Fwww.cyberciti.biz\u002Ffaq\u002Fbash-shell-change-the-color-of-my-shell-prompt-under-linux-or-unix\u002F",{"_key":443,"_type":83,"href":466,"reference":85},"https:\u002F\u002Fterminalsare.sexy\u002F",{"_key":452,"_type":83,"href":468,"reference":85},"https:\u002F\u002Fgithub.com\u002Fcodekitchen\u002Fpipeline",{"_key":470,"_type":60,"children":471,"markDefs":476,"style":68},"f15e60420757",[472],{"_key":473,"_type":64,"marks":474,"text":475},"f15e604207570",[],"Once you’ve gotten your file how you like it, do the extra step of creating a personal dotfiles repo. Keep it sanitized (so no keys, tokens, or passwords), and you’ll have safe access to your familiar prompt and whatever other settings you love at every new computer you work on.",[],{"_key":478,"_type":60,"children":479,"markDefs":484,"style":68},"34340ea29932",[480],{"_key":481,"_type":64,"marks":482,"text":483},"34340ea299320",[],"You’ve made your prompt your friend. Next, let’s look at making what comes after that into an ally too.",[],{"_key":486,"_type":60,"children":487,"markDefs":492,"style":94},"b4b0c4b74194",[488],{"_key":489,"_type":64,"marks":490,"text":491},"b4b0c4b741940",[],"The just-enough approach to learning Bash",[],{"_key":494,"_type":60,"children":495,"markDefs":516,"style":68},"1ab54350f4ee",[496,500,504,508,512],{"_key":497,"_type":64,"marks":498,"text":499},"1ab54350f4ee0",[],"Bash can be a lot, even when you deal with it every day (especially if some of the codebase comes from someone with an aversion to comments). Not every dev ",{"_key":501,"_type":64,"marks":502,"text":503},"1ab54350f4ee1",[284],"must ",{"_key":505,"_type":64,"marks":506,"text":507},"1ab54350f4ee2",[],"know Bash, but every dev will benefit from knowing at least some. If nothing else, it helps you understand exactly what’s happening when you use some long, pasted ",{"_key":509,"_type":64,"marks":510,"text":511},"1ab54350f4ee3",[105],"wget",{"_key":513,"_type":64,"marks":514,"text":515},"1ab54350f4ee4",[]," command to install a new program.",[],{"_key":518,"_type":60,"children":519,"markDefs":533,"style":68},"35a10e0bbac7",[520,524,529],{"_key":521,"_type":64,"marks":522,"text":523},"35a10e0bbac70",[],"The good news is that, with a few strategies, you can navigate most of the Bash you’re likely to encounter without having to become an expert. One of my favorite tools is ",{"_key":525,"_type":64,"marks":526,"text":528},"35a10e0bbac71",[527],"879cc858e14b","Explainshell",{"_key":530,"_type":64,"marks":531,"text":532},"35a10e0bbac72",[],". It can be difficult to get a good, succinct, and completely relevant explanation for what a sample Bash command means, particularly when you get four or five flags deep into it. Man pages are always a good place to start, but Explainshell is an excellent complement. Paste in your command, and the site breaks down each piece so that you actually know what that long string of commands and flags from that seven-year-old Q&A does.",[534],{"_key":527,"_type":83,"href":535,"reference":85},"https:\u002F\u002Fexplainshell.com\u002F",{"_key":537,"_type":60,"children":538,"markDefs":552,"style":68},"e42dbf429481",[539,543,548],{"_key":540,"_type":64,"marks":541,"text":542},"e42dbf4294810",[],"Sometimes, half the work of navigating the command line is figuring out what subcommands are available. If you’re dealing with a complex tool (looking at you, ",{"_key":544,"_type":64,"marks":545,"text":547},"e42dbf4294811",[546],"50d5e88534b5","AWS CLI",{"_key":549,"_type":64,"marks":550,"text":551},"e42dbf4294812",[],") and find yourself referring to the docs more often than you’d like, take a minute to search for an autocomplete feature for it. Sometimes autocomplete is available as a separate but still official package; other times, a third party has made their own complementary tool. That’s one of the joys of the command line: you will rarely encounter a problem that’s unique to you, and there’s a good chance someone has been annoyed into action and fixed it.\n",[553],{"_key":546,"_type":83,"href":554,"reference":85},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fcli\u002Flatest\u002Fuserguide\u002Fcli-configure-completion.html",{"_key":556,"_type":60,"children":557,"markDefs":570,"style":68},"e4fda4c18a97",[558,562,566],{"_key":559,"_type":64,"marks":560,"text":561},"e4fda4c18a970",[],"If you end up continuing to work with the command line (and I hope you do), getting acquainted with pipes demystifies a lot of this work. A pipe in Linux is when you use the ",{"_key":563,"_type":64,"marks":564,"text":565},"e4fda4c18a971",[105],"|",{"_key":567,"_type":64,"marks":568,"text":569},"e4fda4c18a972",[]," symbol to chain together commands, piping output from one to another. In Unix and Linux, each tool was designed to do one thing well, and these individual tools can then be chained together as needed to satisfy more complex needs. This is a strategy I use a lot, particularly when I need to create and sift through output in the terminal.",[],{"_key":572,"_type":60,"children":573,"markDefs":610,"style":68},"7ea661cc9153",[574,578,582,586,590,593,597,601,606],{"_key":575,"_type":64,"marks":576,"text":577},"7ea661cc91530",[],"My most common pipe involves adding ",{"_key":579,"_type":64,"marks":580,"text":581},"7ea661cc91531",[105],"| grep -i $searchTerm",{"_key":583,"_type":64,"marks":584,"text":585},"7ea661cc91532",[]," after a command with long output I’d prefer not to pick through manually, if I’m only searching for one thing. (You can use ",{"_key":587,"_type":64,"marks":588,"text":589},"7ea661cc91533",[105],"-A",{"_key":591,"_type":64,"marks":592,"text":110},"7ea661cc91534",[],{"_key":594,"_type":64,"marks":595,"text":596},"7ea661cc91535",[105],"-B",{"_key":598,"_type":64,"marks":599,"text":600},"7ea661cc91536",[]," to add lines before and after for context, with the number of lines you want as a parameter after each flag. See the ",{"_key":602,"_type":64,"marks":603,"text":605},"7ea661cc91537",[604],"f29a0fc44e9e","grep man page",{"_key":607,"_type":64,"marks":608,"text":609},"7ea661cc91538",[]," to learn more.)",[611],{"_key":604,"_type":83,"href":612,"reference":85},"http:\u002F\u002Flinuxcommand.org\u002Flc3_man_pages\u002Fgrep1.html",{"_key":614,"_type":60,"children":615,"markDefs":679,"style":68},"9cc0d38e8e8a",[616,620,624,628,632,636,640,644,648,652,657,661,666,670,675],{"_key":617,"_type":64,"marks":618,"text":619},"9cc0d38e8e8a0",[],"Also useful: piping the output to ",{"_key":621,"_type":64,"marks":622,"text":623},"9cc0d38e8e8a1",[105],"less",{"_key":625,"_type":64,"marks":626,"text":627},"9cc0d38e8e8a2",[],", which is better if I do want to scroll through the whole output, or at least navigate it and search within the open file, using ",{"_key":629,"_type":64,"marks":630,"text":631},"9cc0d38e8e8a3",[105],"\u002F$searchTerm",{"_key":633,"_type":64,"marks":634,"text":635},"9cc0d38e8e8a4",[],", ",{"_key":637,"_type":64,"marks":638,"text":639},"9cc0d38e8e8a5",[105],"n",{"_key":641,"_type":64,"marks":642,"text":643},"9cc0d38e8e8a6",[]," to see the next entry, and ",{"_key":645,"_type":64,"marks":646,"text":647},"9cc0d38e8e8a7",[105],"N",{"_key":649,"_type":64,"marks":650,"text":651},"9cc0d38e8e8a8",[]," to see the previous. You can also use ",{"_key":653,"_type":64,"marks":654,"text":656},"9cc0d38e8e8a9",[655,105],"04b10cf28724","cut",{"_key":658,"_type":64,"marks":659,"text":660},"9cc0d38e8e8a10",[]," or ",{"_key":662,"_type":64,"marks":663,"text":665},"9cc0d38e8e8a11",[664,105],"8c1999f98609","awk",{"_key":667,"_type":64,"marks":668,"text":669},"9cc0d38e8e8a12",[]," to manipulate the output, which is particularly useful if you need to create a file of that output with a very specific format. And if you find yourself parsing JSON output much, getting acquainted with ",{"_key":671,"_type":64,"marks":672,"text":674},"9cc0d38e8e8a13",[673],"df2c01f277a7","jq",{"_key":676,"_type":64,"marks":677,"text":678},"9cc0d38e8e8a14",[]," can save you some time.",[680,682,684],{"_key":655,"_type":83,"href":681,"reference":85},"https:\u002F\u002Fwww.geeksforgeeks.org\u002Fcut-command-linux-examples\u002F",{"_key":664,"_type":83,"href":683,"reference":85},"https:\u002F\u002Fwww.cyberciti.biz\u002Ffaq\u002Fbash-scripting-using-awk\u002F",{"_key":673,"_type":83,"href":685,"reference":85},"https:\u002F\u002Fstedolan.github.io\u002Fjq\u002F",{"_key":687,"_type":60,"children":688,"markDefs":770,"style":68},"c24eac9b601f",[689,693,697,701,705,709,713,717,720,724,728,732,736,739,743,747,751,755,759,763,766],{"_key":690,"_type":64,"marks":691,"text":692},"c24eac9b601f0",[],"Let’s look at some of the other conveniences the command line offers. ",{"_key":694,"_type":64,"marks":695,"text":696},"c24eac9b601f1",[105],"sudo !!",{"_key":698,"_type":64,"marks":699,"text":700},"c24eac9b601f2",[]," repeats your previous command with ",{"_key":702,"_type":64,"marks":703,"text":704},"c24eac9b601f3",[105],"sudo",{"_key":706,"_type":64,"marks":707,"text":708},"c24eac9b601f4",[]," pasted in front of it. (The ",{"_key":710,"_type":64,"marks":711,"text":712},"c24eac9b601f5",[105],"!!",{"_key":714,"_type":64,"marks":715,"text":716},"c24eac9b601f6",[]," is Unix\u002FLinux shorthand for “the previous command” and can be used in other situations too.) So if you ran something fairly involved but forgot that it needed root-level permissions, just use ",{"_key":718,"_type":64,"marks":719,"text":696},"c24eac9b601f7",[105],{"_key":721,"_type":64,"marks":722,"text":723},"c24eac9b601f8",[],". Similarly useful: ",{"_key":725,"_type":64,"marks":726,"text":727},"c24eac9b601f9",[105],"!$",{"_key":729,"_type":64,"marks":730,"text":731},"c24eac9b601f10",[],", which gives you the value of the first argument of the previous command, so ",{"_key":733,"_type":64,"marks":734,"text":735},"c24eac9b601f11",[105],"ls ~\u002FDesktop",{"_key":737,"_type":64,"marks":738,"text":110},"c24eac9b601f12",[],{"_key":740,"_type":64,"marks":741,"text":742},"c24eac9b601f13",[105],"cd !$",{"_key":744,"_type":64,"marks":745,"text":746},"c24eac9b601f14",[]," would show you the files in ",{"_key":748,"_type":64,"marks":749,"text":750},"c24eac9b601f15",[105],"~\u002FDesktop",{"_key":752,"_type":64,"marks":753,"text":754},"c24eac9b601f16",[]," and then move you to that directory. And if you need to return to your previous directory and don’t remember the whole path, just type ",{"_key":756,"_type":64,"marks":757,"text":758},"c24eac9b601f17",[105],"cd -",{"_key":760,"_type":64,"marks":761,"text":762},"c24eac9b601f18",[]," to back up one ",{"_key":764,"_type":64,"marks":765,"text":321},"c24eac9b601f19",[105],{"_key":767,"_type":64,"marks":768,"text":769},"c24eac9b601f20",[]," move.",[],{"_key":772,"_type":60,"children":773,"markDefs":778,"style":94},"9bd136ee5b1e",[774],{"_key":775,"_type":64,"marks":776,"text":777},"9bd136ee5b1e0",[],"Faster navigation in text",[],{"_key":780,"_type":60,"children":781,"markDefs":786,"style":68},"6374b9cdfa71",[782],{"_key":783,"_type":64,"marks":784,"text":785},"6374b9cdfa710",[],"Here’s a seemingly simple thing I learned a few years ago that regularly startles even long-tenured engineers. Did you know that you can click into the middle of a line in your terminal? Alt-click will move your cursor to where you need to go. It still requires moving your hands off the keyboard, so it’s a little clunky compared with some keyboard navigation. But it’s a useful tool, and oddly impressive—I’ve stunned people by doing that in front of them and then got the joy of sharing it with them. Now you know it too.",[],{"_key":788,"_type":60,"children":789,"markDefs":811,"style":68},"a357c70a67c4",[790,794,799,803,807],{"_key":791,"_type":64,"marks":792,"text":793},"a357c70a67c40",[],"The keyboard shortcut methods of moving your cursor can be equally impressive, though. You can get a lot of mileage out of terminal keyboard shortcuts (to say nothing about making your work a little easier). You can jump to the beginning or end of the line with ctrl-A or E, cut the line from your cursor to the beginning of the line with ctrl-U, or delete the previous word with ctrl-W. Here’s ",{"_key":795,"_type":64,"marks":796,"text":798},"a357c70a67c41",[797],"770fb27e9459","Apple’s long list of keyboard shortcuts for the terminal",{"_key":800,"_type":64,"marks":801,"text":802},"a357c70a67c42",[],", which generally work on a Linux command line too. I suggest picking a couple you want to adopt, writing them on a sticky note and putting it on your monitor, and making yourself do it the new way until it feels natural. Then move to the next commands you want to commit to muscle memory, and soon enough, you too can be very efficient… if very confusing to watch for those who don’t work this way. (But then you get to do the kind thing of teaching ",{"_key":804,"_type":64,"marks":805,"text":806},"a357c70a67c43",[284],"them",{"_key":808,"_type":64,"marks":809,"text":810},"a357c70a67c44",[]," the thing you just learned, and the cycle continues.)",[812],{"_key":797,"_type":83,"href":813,"reference":85},"https:\u002F\u002Fsupport.apple.com\u002Fguide\u002Fterminal\u002Fkeyboard-shortcuts-trmlshtcts\u002Fmac",{"_key":815,"_type":60,"children":816,"markDefs":821,"style":94},"05693ba27b65",[817],{"_key":818,"_type":64,"marks":819,"text":820},"05693ba27b650",[],"Time travel, terminal style",[],{"_key":823,"_type":60,"children":824,"markDefs":843,"style":68},"cea0fea004f6",[825,829,832,836,840],{"_key":826,"_type":64,"marks":827,"text":828},"cea0fea004f60",[],"If you only need to refer to your last command, ",{"_key":830,"_type":64,"marks":831,"text":712},"cea0fea004f61",[105],{"_key":833,"_type":64,"marks":834,"text":835},"cea0fea004f62",[]," or just arrowing up and down are great, straightforward options. But what if you need to dig deeper into the past? To search your terminal history, type ctrl-R and then begin typing. Want to see the whole thing? Just type ",{"_key":837,"_type":64,"marks":838,"text":839},"cea0fea004f63",[105],"history",{"_key":841,"_type":64,"marks":842,"text":118},"cea0fea004f64",[],[],{"_key":845,"_type":60,"children":846,"markDefs":918,"style":68},"88c78fa194dd",[847,851,855,859,862,866,870,873,877,881,885,888,892,896,899,903,906,910,915],{"_key":848,"_type":64,"marks":849,"text":850},"88c78fa194dd0",[],"The Mac default is 500 history entries, which is not that much for a heavily used terminal. You can check your history length with ",{"_key":852,"_type":64,"marks":853,"text":854},"88c78fa194dd1",[105],"echo $HISTFILESIZE",{"_key":856,"_type":64,"marks":857,"text":858},"88c78fa194dd2",[],". Want to increase its retention? Time to edit ",{"_key":860,"_type":64,"marks":861,"text":114},"88c78fa194dd3",[105],{"_key":863,"_type":64,"marks":864,"text":865},"88c78fa194dd4",[]," again. Just set ",{"_key":867,"_type":64,"marks":868,"text":869},"88c78fa194dd5",[105],"HISTSIZE",{"_key":871,"_type":64,"marks":872,"text":110},"88c78fa194dd6",[],{"_key":874,"_type":64,"marks":875,"text":876},"88c78fa194dd7",[105],"HISTFILESIZE",{"_key":878,"_type":64,"marks":879,"text":880},"88c78fa194dd8",[]," to a very large number—10000000 is a good option. Add ",{"_key":882,"_type":64,"marks":883,"text":884},"88c78fa194dd9",[105],"export HISTSIZE=10000000",{"_key":886,"_type":64,"marks":887,"text":110},"88c78fa194dd10",[],{"_key":889,"_type":64,"marks":890,"text":891},"88c78fa194dd11",[105],"export HISTFILESIZE=10000000",{"_key":893,"_type":64,"marks":894,"text":895},"88c78fa194dd12",[]," to ",{"_key":897,"_type":64,"marks":898,"text":114},"88c78fa194dd13",[105],{"_key":900,"_type":64,"marks":901,"text":902},"88c78fa194dd14",[]," (and don’t forget to ",{"_key":904,"_type":64,"marks":905,"text":175},"88c78fa194dd15",[105],{"_key":907,"_type":64,"marks":908,"text":909},"88c78fa194dd16",[]," again or open a new terminal window for it to take effect). For more details on the difference between these two variables, check out the accepted answer ",{"_key":911,"_type":64,"marks":912,"text":914},"88c78fa194dd17",[913],"c200e34330ff","here",{"_key":916,"_type":64,"marks":917,"text":118},"88c78fa194dd18",[],[919],{"_key":913,"_type":83,"href":920,"reference":85},"https:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F19454837\u002Fbash-histsize-vs-histfilesize",{"_key":922,"_type":60,"children":923,"markDefs":943,"style":68},"569ad53e6106",[924,928,932,936,940],{"_key":925,"_type":64,"marks":926,"text":927},"569ad53e61060",[],"Now that your history is (more) infinite, it might be good to know how to clean it up. It lives at ",{"_key":929,"_type":64,"marks":930,"text":931},"569ad53e61061",[105],"~\u002F.bash_history",{"_key":933,"_type":64,"marks":934,"text":935},"569ad53e61062",[],", which means you can delete it entirely with ",{"_key":937,"_type":64,"marks":938,"text":939},"569ad53e61063",[105],"rm ~\u002F.bash_history",{"_key":941,"_type":64,"marks":942,"text":118},"569ad53e61064",[],[],{"_key":945,"_type":60,"children":946,"markDefs":951,"style":68},"6d3bd144adaa",[947],{"_key":948,"_type":64,"marks":949,"text":950},"6d3bd144adaa0",[],"But let’s look at some of the other information accessible via the command line: environment variables.",[],{"_key":953,"_type":60,"children":954,"markDefs":959,"style":94},"dc298df97d35",[955],{"_key":956,"_type":64,"marks":957,"text":958},"dc298df97d350",[],"Your terminal’s hidden values: revealed!",[],{"_key":961,"_type":60,"children":962,"markDefs":1013,"style":68},"fa1d9e655855",[963,967,971,975,978,982,986,990,994,997,1001,1005,1009],{"_key":964,"_type":64,"marks":965,"text":966},"fa1d9e6558550",[],"Environment variables can come from many different places. Some are just part of your OS; you can see some common ones ",{"_key":968,"_type":64,"marks":969,"text":914},"fa1d9e6558551",[970],"8b445d7de47f",{"_key":972,"_type":64,"marks":973,"text":974},"fa1d9e6558552",[],". Others may be put in place via ",{"_key":976,"_type":64,"marks":977,"text":114},"fa1d9e6558553",[105],{"_key":979,"_type":64,"marks":980,"text":981},"fa1d9e6558554",[]," when you set them yourself in the terminal or via config or other files run on your system. It’s quick and easy to type ",{"_key":983,"_type":64,"marks":984,"text":985},"fa1d9e6558555",[105],"echo $varName",{"_key":987,"_type":64,"marks":988,"text":989},"fa1d9e6558556",[]," in the terminal and see if a specific value is set, but what if you don’t know what variables have been set? That’s where ",{"_key":991,"_type":64,"marks":992,"text":993},"fa1d9e6558557",[105],"set",{"_key":995,"_type":64,"marks":996,"text":635},"fa1d9e6558558",[],{"_key":998,"_type":64,"marks":999,"text":1000},"fa1d9e6558559",[105],"printenv",{"_key":1002,"_type":64,"marks":1003,"text":1004},"fa1d9e65585510",[],", and ",{"_key":1006,"_type":64,"marks":1007,"text":1008},"fa1d9e65585511",[105],"env",{"_key":1010,"_type":64,"marks":1011,"text":1012},"fa1d9e65585512",[]," come in.",[1014],{"_key":970,"_type":83,"href":1015,"reference":85},"https:\u002F\u002Fbash.cyberciti.biz\u002Fguide\u002FVariables#Commonly_Used_Shell_Variables",{"_key":1017,"_type":60,"children":1018,"markDefs":1023,"style":68},"dc2efb42fec0",[1019],{"_key":1020,"_type":64,"marks":1021,"text":1022},"dc2efb42fec00",[],"These three programs overlap some in output but aren’t identical. Here’s a quick rundown:",[],{"_key":1025,"_type":60,"children":1026,"level":326,"listItem":327,"markDefs":1035,"style":68},"25313c232cd9",[1027,1031],{"_key":1028,"_type":64,"marks":1029,"text":993},"25313c232cd90",[105,1030],"6f9546b413c0",{"_key":1032,"_type":64,"marks":1033,"text":1034},"25313c232cd91",[],"is more complete and will include variables you’ve set in addition to the ones inherent to your environment.",[1036],{"_key":1030,"_type":83,"href":1037,"reference":85},"https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fbash\u002Fmanual\u002Fhtml_node\u002FThe-Set-Builtin.html",{"_key":1039,"_type":60,"children":1040,"level":326,"listItem":327,"markDefs":1078,"style":68},"64642453c437",[1041,1045,1048,1052,1056,1059,1063,1066,1070,1074],{"_key":1042,"_type":64,"marks":1043,"text":1000},"64642453c4370",[1044,105],"7ba3f3a37328",{"_key":1046,"_type":64,"marks":1047,"text":110},"64642453c4371",[],{"_key":1049,"_type":64,"marks":1050,"text":1008},"64642453c4372",[1051,105],"72d75ccf8891",{"_key":1053,"_type":64,"marks":1054,"text":1055},"64642453c4373",[]," offer similar output of built-in environment variables, but ",{"_key":1057,"_type":64,"marks":1058,"text":1008},"64642453c4374",[105],{"_key":1060,"_type":64,"marks":1061,"text":1062},"64642453c4375",[]," has more robust capabilities beyond ",{"_key":1064,"_type":64,"marks":1065,"text":1000},"64642453c4376",[105],{"_key":1067,"_type":64,"marks":1068,"text":1069},"64642453c4377",[],"’s simple display purposes, including running a program in a modified environment. The accepted answer ",{"_key":1071,"_type":64,"marks":1072,"text":914},"64642453c4378",[1073],"fc63548fe974",{"_key":1075,"_type":64,"marks":1076,"text":1077},"64642453c4379",[]," provides some deep history about the existence of both commands and how and why they differ.",[1079,1081,1083],{"_key":1044,"_type":83,"href":1080,"reference":85},"http:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman1\u002Fprintenv.1.html",{"_key":1051,"_type":83,"href":1082,"reference":85},"http:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman1\u002Fenv.1.html",{"_key":1073,"_type":83,"href":1084,"reference":85},"https:\u002F\u002Funix.stackexchange.com\u002Fquestions\u002F123473\u002Fwhat-is-the-difference-between-env-and-printenv",{"_key":1086,"_type":60,"children":1087,"markDefs":1092,"style":68},"53e0f4b935d9",[1088],{"_key":1089,"_type":64,"marks":1090,"text":1091},"53e0f4b935d90",[],"You’ll likely get what you need with set, though. The output is longer, which means you’re more likely to need to pipe to grep or less, but it’s also more likely that you’ll find what you’re looking for.",[],{"_key":1094,"_type":60,"children":1095,"markDefs":1100,"style":94},"1b839ef78617",[1096],{"_key":1097,"_type":64,"marks":1098,"text":1099},"1b839ef786170",[],"Better living through ops skills",[],{"_key":1102,"_type":60,"children":1103,"markDefs":1115,"style":68},"12227606c1c6",[1104,1108,1111],{"_key":1105,"_type":64,"marks":1106,"text":1107},"12227606c1c60",[],"You’ve learned how to customize your command line and make it friendlier for troubleshooting. You’ve learned how to unearth surprise values hiding in your local environment variables. You’ve learned some of how to look like a wizard with aliases and keyboard shortcuts. And I bet you can start spreading the good word of ",{"_key":1109,"_type":64,"marks":1110,"text":114},"12227606c1c61",[105],{"_key":1112,"_type":64,"marks":1113,"text":1114},"12227606c1c62",[],". There’s more to Bash and terminal tricks than we’ve laid out here, but it’s yours to discover online—or just ask your friendly local ops engineer out for coffee and ask them their favorite terminal customization. You’ll probably learn more than you expect.",[],"2020\u002F02\u002F12","DevOps job posts often ask for automation skills, which is a positive way of asking for someone who’s professionally lazy in a way that results in efficiency. The good news is that developers can also learn a few tricks from the land of ops to make their days easier and their work better. ",{"_type":52,"asset":1119},{"_ref":1120,"_type":1121},"image-2b614e170daf7e4001aa24a204cf9ca2f5400b4d-2119x1414-jpg","reference",{"code":1123,"language":1124},"\u003C!-- wp:paragraph -->\n\u003Cp>A terminal is never just a terminal. An elaborate prompt can mean someone digs deeply into optimizing the tools she uses, while the information it contains can give you an idea of what kind of engineering she’s done. What you type into the command line can tell you about environment variables, hidden configs, and OS defaults you never knew about. You can make it speak shorthand only known to your terminal and you. And all of it can help you work more efficiently and effectively. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBash_(Unix_shell)\">Bash\u003C\u002Fa> (a term used for both the Unix shell and the command language; I’ll be using the second meaning in this post) is usually a skill mentioned only in job descriptions for site reliability engineers and other ops jobs. Those same job posts often ask for automation skills, which is a positive way of asking for someone who’s professionally lazy in a way that results in efficiency. The good news is that developers can also learn a few tricks from the land of ops to make their days easier and their work better.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Your own personal(ized) terminal\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are lots of ways to customize your command line prompt and terminal to make you more efficient at work. We’ll start with possibly the most powerful one: meet \u003Ccode>~\u002F.bashrc\u003C\u002Fcode> and \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode>. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>This file exists under several different names, depending on your OS and what you’re trying to accomplish, and it can hold a lot of things that can make your life easier: shorter aliases for common commands, your custom \u003Ca href=\"http:\u002F\u002Fwww.linfo.org\u002Fpath_env_var.html\">PATH\u003C\u002Fa>, Bash functions to populate your prompt with environment information, history length, command line completion, default editors, and more. With a little observation of your terminal habits (and a little knowledge of \u003Ca href=\"http:\u002F\u002Ftldp.org\u002FHOWTO\u002FBash-Prog-Intro-HOWTO.html\">Bash\u003C\u002Fa>, the command language used in many terminals), you can put all kinds of things in here that will make your life easier. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Which file you use depends on your OS. \u003Ca href=\"http:\u002F\u002Fwww.joshstaiger.org\u002Farchives\u002F2005\u002F07\u002Fbash_profile_vs.html\">This post\u003C\u002Fa> gives a rundown on the purposes and tradeoffs of the two files. If you use a Mac, though, use \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode>. Run \u003Ccode>source ~\u002F.bash_profile\u003C\u002Fcode> once you’ve saved your changes, so they’re live in your terminal (or just close your terminal window and open a new one).\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>What else should you put in your beautifully customized new file? Let’s start with aliases.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When automating things in ops work, I watch what operations I do more than a couple of times, make notes on what I did, and put those on a list of likely script ideas. Once it’s clear I’ll be doing it again and again, I know it’s worth the time to put a solution into code. You can do the same thing with your own habits. What commands are you typing all the time? What values are you frequently using? These can all be aliases. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>For example, \u003Ccode>git commit\u003C\u002Fcode> and \u003Ccode>git checkout\u003C\u002Fcode> can become \u003Ccode>gc \u003C\u002Fcode>and \u003Ccode>gco \u003C\u002Fcode>(or whatever matches your mental map of abbreviations). But you can go further than that by aliasing long commands with lots of flags and arguments. Here’s how to make one:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>alias $preferredAlias='$commandToAlias'\u003C\u002Fcode>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>alias\u003C\u002Fcode> is the Bash command here (you can make an alias directly on the command line too, and it will only be available for that session until you close that terminal). \u003Ccode>$preferredAlias\u003C\u002Fcode> is your nice, short name for \u003Ccode>$commandToAlias\u003C\u002Fcode>, the longer, more cumbersome command you’re typing all the time. No spaces around the \u003Ccode>= \u003C\u002Fcode>and don’t forget the single \u003Cem>straight\u003C\u002Fem> quotes around the command you’re aliasing. You can also chain commands together using \u003Ccode>&amp;&amp;\u003C\u002Fcode>. Ever sat next to someone whose command line navigation was completely opaque because they’d optimized their work into a flurry of short aliases? Now you can be that person, too. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Here are a couple I use:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>mkcd='mkdir $1 &amp;&amp; cd $1'\u003C\u002Fcode> (consolidating a common pair of operations; the $1 takes the first argument, in this case the new file you want to \u003Ccode>cd\u003C\u002Fcode> into)\u003C\u002Fli>\u003Cli>\u003Ccode>tfplan='terraform init &amp;&amp; terraform plan'\u003C\u002Fcode> (preventing a common mistake for me; this can be used to chain any two commonly paired commands)\u003C\u002Fli>\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you frequently work across different OSes (varying flavors of Linux, Mac OS), you can go a little further by creating multiple tailored dotfiles that assign slightly differing commands that achieve the same thing to the same alias. No more remembering the minute differences that only come up every month or two—it’s the same couple of characters wherever you are. If you’re prone to misspelling commands (looking at you, \u003Ccode>gerp\u003C\u002Fcode>), you can alias those too. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now let’s look at another capability of dotfiles: customizing your prompt.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>A constant source of truth on the command line\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Your terminal prompt is one of the places you can be kindest to yourself, putting what you need in there so you don’t have to type \u003Ccode>pwd\u003C\u002Fcode> all the time or wonder exactly how long ago you typed that fateful command. At a minimum, I suggest adding a timestamp with minutes to it; that way, if you need to backtrack through recent work to tie cause to effect, you can precisely anchor an action’s time with minimal work. Beyond that, I also suggest adding your working directory and current git branch. My go-to tool for setting this up inexpensively is \u003Ca href=\"http:\u002F\u002Fezprompt.net\u002F\">EzPrompt\u003C\u002Fa>, which lets you drag and drop your desired prompt elements and returns the Bash you need to add to \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode>. It’s a good, simple start when you’re first cultivating your dotfiles. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you want to get a little more involved, you can try something like \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fpowerline\u002Fpowerline\">Powerline\u003C\u002Fa>, which looks slick and offers more involved status information. And if you want to roll your own, self-educate about \u003Ca href=\"http:\u002F\u002Fwww.marinamele.com\u002F2014\u002F05\u002Fcustomize-colors-of-your-terminal-in-mac-os-x.html\">how to work with colors in the terminal\u003C\u002Fa> and \u003Ca href=\"https:\u002F\u002Fwww.cyberciti.biz\u002Ffaq\u002Fbash-shell-change-the-color-of-my-shell-prompt-under-linux-or-unix\u002F\">the elements you can add to your prompt\u003C\u002Fa>. There’s a whole galaxy of options out there, and \u003Ca href=\"https:\u002F\u002Fterminalsare.sexy\u002F\">Terminals Are Sexy\u003C\u002Fa> provides guidance to some of the constellations you can explore. Hand-crafted customization is a great way to get used to Bash syntax. If you’re looking to do something more complex with a lengthier command, \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcodekitchen\u002Fpipeline\">Pipeline\u003C\u002Fa> provides an interactive environment to help you refine your output, showing you what your command produces as you edit it.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Once you’ve gotten your file how you like it, do the extra step of creating a personal dotfiles repo. Keep it sanitized (so no keys, tokens, or passwords), and you’ll have safe access to your familiar prompt and whatever other settings you love at every new computer you work on. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You’ve made your prompt your friend. Next, let’s look at making what comes after that into an ally too.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:block {\"ref\":15001} \u002F-->\n\n\u003C!-- wp:heading -->\n\u003Ch2>The just-enough approach to learning Bash\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Bash can be a lot, even when you deal with it every day (especially if some of the codebase comes from someone with an aversion to comments). Not every dev \u003Cem>must \u003C\u002Fem>know Bash, but every dev will benefit from knowing at least some. If nothing else, it helps you understand exactly what’s happening when you use some long, pasted \u003Ccode>wget\u003C\u002Fcode> command to install a new program. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The good news is that, with a few strategies, you can navigate most of the Bash you’re likely to encounter without having to become an expert. One of my favorite tools is \u003Ca href=\"https:\u002F\u002Fexplainshell.com\u002F\">Explainshell\u003C\u002Fa>. It can be difficult to get a good, succinct, and completely relevant explanation for what a sample Bash command means, particularly when you get four or five flags deep into it. Man pages are always a good place to start, but Explainshell is an excellent complement. Paste in your command, and the site breaks down each piece so that you actually know what that long string of commands and flags from that seven-year-old Q&amp;A does. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Sometimes, half the work of navigating the command line is figuring out what subcommands are available. If you’re dealing with a complex tool (looking at you, \u003Ca href=\"https:\u002F\u002Fdocs.aws.amazon.com\u002Fcli\u002Flatest\u002Fuserguide\u002Fcli-configure-completion.html\">AWS CLI\u003C\u002Fa>) and find yourself referring to the docs more often than you’d like, take a minute to search for an autocomplete feature for it. Sometimes autocomplete is available as a separate but still official package; other times, a third party has made their own complementary tool. That’s one of the joys of the command line: you will rarely encounter a problem that’s unique to you, and there’s a good chance someone has been annoyed into action and fixed it.\u003Cbr>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you end up continuing to work with the command line (and I hope you do), getting acquainted with pipes demystifies a lot of this work. A pipe in Linux is when you use the \u003Ccode>|\u003C\u002Fcode> symbol to chain together commands, piping output from one to another. In Unix and Linux, each tool was designed to do one thing well, and these individual tools can then be chained together as needed to satisfy more complex needs. This is a strategy I use a lot, particularly when I need to create and sift through output in the terminal. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>My most common pipe involves adding \u003Ccode>| grep -i $searchTerm\u003C\u002Fcode> after a command with long output I’d prefer not to pick through manually, if I’m only searching for one thing. (You can use \u003Ccode>-A\u003C\u002Fcode> and \u003Ccode>-B\u003C\u002Fcode> to add lines before and after for context, with the number of lines you want as a parameter after each flag. See the \u003Ca href=\"http:\u002F\u002Flinuxcommand.org\u002Flc3_man_pages\u002Fgrep1.html\">grep man page\u003C\u002Fa> to learn more.) \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Also useful: piping the output to \u003Ccode>less\u003C\u002Fcode>, which is better if I do want to scroll through the whole output, or at least navigate it and search within the open file, using \u003Ccode>\u002F$searchTerm\u003C\u002Fcode>, \u003Ccode>n\u003C\u002Fcode> to see the next entry, and \u003Ccode>N\u003C\u002Fcode> to see the previous. You can also use \u003Ca href=\"https:\u002F\u002Fwww.geeksforgeeks.org\u002Fcut-command-linux-examples\u002F\">\u003Ccode>cut\u003C\u002Fcode>\u003C\u002Fa> or \u003Ca href=\"https:\u002F\u002Fwww.cyberciti.biz\u002Ffaq\u002Fbash-scripting-using-awk\u002F\">\u003Ccode>awk\u003C\u002Fcode>\u003C\u002Fa> to manipulate the output, which is particularly useful if you need to create a file of that output with a very specific format. And if you find yourself parsing JSON output much, getting acquainted with \u003Ca href=\"https:\u002F\u002Fstedolan.github.io\u002Fjq\u002F\">jq\u003C\u002Fa> can save you some time.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Let’s look at some of the other conveniences the command line offers. \u003Ccode>sudo !!\u003C\u002Fcode> repeats your previous command with \u003Ccode>sudo\u003C\u002Fcode> pasted in front of it. (The \u003Ccode>!!\u003C\u002Fcode> is Unix\u002FLinux shorthand for “the previous command” and can be used in other situations too.) So if you ran something fairly involved but forgot that it needed root-level permissions, just use \u003Ccode>sudo !!\u003C\u002Fcode>. Similarly useful: \u003Ccode>!$\u003C\u002Fcode>, which gives you the value of the first argument of the previous command, so \u003Ccode>ls ~\u002FDesktop\u003C\u002Fcode> and \u003Ccode>cd !$\u003C\u002Fcode> would show you the files in \u003Ccode>~\u002FDesktop\u003C\u002Fcode> and then move you to that directory. And if you need to return to your previous directory and don’t remember the whole path, just type \u003Ccode>cd -\u003C\u002Fcode> to back up one \u003Ccode>cd\u003C\u002Fcode> move.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Faster navigation in text\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Here’s a seemingly simple thing I learned a few years ago that regularly startles even long-tenured engineers. Did you know that you can click into the middle of a line in your terminal? Alt-click will move your cursor to where you need to go. It still requires moving your hands off the keyboard, so it’s a little clunky compared with some keyboard navigation. But it’s a useful tool, and oddly impressive—I’ve stunned people by doing that in front of them and then got the joy of sharing it with them. Now you know it too. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The keyboard shortcut methods of moving your cursor can be equally impressive, though. You can get a lot of mileage out of terminal keyboard shortcuts (to say nothing about making your work a little easier). You can jump to the beginning or end of the line with ctrl-A or E, cut the line from your cursor to the beginning of the line with ctrl-U, or delete the previous word with ctrl-W. Here’s \u003Ca href=\"https:\u002F\u002Fsupport.apple.com\u002Fguide\u002Fterminal\u002Fkeyboard-shortcuts-trmlshtcts\u002Fmac\">Apple’s long list of keyboard shortcuts for the terminal\u003C\u002Fa>, which generally work on a Linux command line too. I suggest picking a couple you want to adopt, writing them on a sticky note and putting it on your monitor, and making yourself do it the new way until it feels natural. Then move to the next commands you want to commit to muscle memory, and soon enough, you too can be very efficient… if very confusing to watch for those who don’t work this way. (But then you get to do the kind thing of teaching \u003Cem>them\u003C\u002Fem> the thing you just learned, and the cycle continues.)\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Time travel, terminal style\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you only need to refer to your last command, \u003Ccode>!!\u003C\u002Fcode> or just arrowing up and down are great, straightforward options. But what if you need to dig deeper into the past? To search your terminal history, type ctrl-R and then begin typing. Want to see the whole thing? Just type \u003Ccode>history\u003C\u002Fcode>. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The Mac default is 500 history entries, which is not that much for a heavily used terminal. You can check your history length with \u003Ccode>echo $HISTFILESIZE\u003C\u002Fcode>. Want to increase its retention? Time to edit \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode> again. Just set \u003Ccode>HISTSIZE\u003C\u002Fcode> and \u003Ccode>HISTFILESIZE\u003C\u002Fcode> to a very large number—10000000 is a good option. Add \u003Ccode>export HISTSIZE=10000000\u003C\u002Fcode> and \u003Ccode>export HISTFILESIZE=10000000\u003C\u002Fcode> to \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode> (and don’t forget to \u003Ccode>source ~\u002F.bash_profile\u003C\u002Fcode> again or open a new terminal window for it to take effect). For more details on the difference between these two variables, check out the accepted answer \u003Ca href=\"https:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F19454837\u002Fbash-histsize-vs-histfilesize\">here\u003C\u002Fa>. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Now that your history is (more) infinite, it might be good to know how to clean it up. It lives at \u003Ccode>~\u002F.bash_history\u003C\u002Fcode>, which means you can delete it entirely with \u003Ccode>rm ~\u002F.bash_history\u003C\u002Fcode>.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>But let’s look at some of the other information accessible via the command line: environment variables.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Your terminal’s hidden values: revealed!\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Environment variables can come from many different places. Some are just part of your OS; you can see some common ones \u003Ca href=\"https:\u002F\u002Fbash.cyberciti.biz\u002Fguide\u002FVariables#Commonly_Used_Shell_Variables\">here\u003C\u002Fa>. Others may be put in place via \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode> when you set them yourself in the terminal or via config or other files run on your system. It’s quick and easy to type \u003Ccode>echo $varName\u003C\u002Fcode> in the terminal and see if a specific value is set, but what if you don’t know what variables have been set? That’s where \u003Ccode>set\u003C\u002Fcode>, \u003Ccode>printenv\u003C\u002Fcode>, and \u003Ccode>env\u003C\u002Fcode> come in. \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>These three programs overlap some in output but aren’t identical. Here’s a quick rundown:&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003Cli>\u003Ccode>\u003Ca href=\"https:\u002F\u002Fwww.gnu.org\u002Fsoftware\u002Fbash\u002Fmanual\u002Fhtml_node\u002FThe-Set-Builtin.html\">set\u003C\u002Fa> \u003C\u002Fcode>is more complete and will include variables you’ve set in addition to the ones inherent to your environment.&nbsp;\u003C\u002Fli>\u003Cli>\u003Ca href=\"http:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman1\u002Fprintenv.1.html\">\u003Ccode>printenv\u003C\u002Fcode>\u003C\u002Fa> and \u003Ca href=\"http:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman1\u002Fenv.1.html\">\u003Ccode>env\u003C\u002Fcode>\u003C\u002Fa> offer similar output of built-in environment variables, but \u003Ccode>env\u003C\u002Fcode> has more robust capabilities beyond \u003Ccode>printenv\u003C\u002Fcode>’s simple display purposes, including running a program in a modified environment. The accepted answer \u003Ca href=\"https:\u002F\u002Funix.stackexchange.com\u002Fquestions\u002F123473\u002Fwhat-is-the-difference-between-env-and-printenv\">here\u003C\u002Fa> provides some deep history about the existence of both commands and how and why they differ.&nbsp;\u003C\u002Fli>\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You’ll likely get what you need with set, though. The output is longer, which means you’re more likely to need to pipe to grep or less, but it’s also more likely that you’ll find what you’re looking for.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2>Better living through ops skills\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You’ve learned how to customize your command line and make it friendlier for troubleshooting. You’ve learned how to unearth surprise values hiding in your local environment variables. You’ve learned some of how to look like a wizard with aliases and keyboard shortcuts. And I bet you can start spreading the good word of \u003Ccode>~\u002F.bash_profile\u003C\u002Fcode>. There’s more to Bash and terminal tricks than we’ve laid out here, but it’s yours to discover online—or just ask your friendly local ops engineer out for coffee and ask them their favorite terminal customization. You’ll probably learn more than you expect.  \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->","html","2020-02-12T14:47:47.000Z",{"current":1127},"when-laziness-is-efficient-make-the-most-of-your-command-line",[1129,1136,1141,1143,1148,1153,1157,1162],{"_createdAt":1130,"_id":1131,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1134,"title":1135},"2023-05-23T16:43:21Z","wp-tagcat-bash","9HpbCsT2tq0xwozQfkc4ih","blogTag",{"current":1135},"bash",{"_createdAt":1130,"_id":1137,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1138,"title":1140},"wp-tagcat-bulletin",{"current":1139},"bulletin","Bulletin",{"_createdAt":1130,"_id":1137,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1142,"title":1140},{"current":1139},{"_createdAt":1130,"_id":1144,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1145,"title":1147},"wp-tagcat-code-for-a-living",{"current":1146},"code-for-a-living","Code for a Living",{"_createdAt":1130,"_id":1149,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1150,"title":1152},"wp-tagcat-command-line",{"current":1151},"command-line","command line",{"_createdAt":1130,"_id":1154,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1155,"title":1156},"wp-tagcat-devops",{"current":1156},"devops",{"_createdAt":1130,"_id":1158,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1159,"title":1161},"wp-tagcat-stackoverflow",{"current":1160},"stackoverflow","Stackoverflow",{"_createdAt":1130,"_id":1158,"_rev":1132,"_type":1133,"_updatedAt":1130,"slug":1163,"title":1161},{"current":1160},"When laziness is efficient: Make the most of your command line",[1166,1172,1178,1184],{"_id":1167,"publishedAt":1168,"slug":1169,"sponsored":85,"title":1171},"76c9771b-34e6-4d98-8641-ecefc711f0ef","2026-07-06T15:23:34.559Z",{"_type":10,"current":1170},"when-the-sensor-starts-thinking-snortml-agentic-ai-and-the-evolving-architecture-of-intrusion-detection","When the sensor starts thinking: SnortML, agentic AI, and the evolving architecture of intrusion detection",{"_id":1173,"publishedAt":1174,"slug":1175,"sponsored":85,"title":1177},"28e560af-f0aa-4d46-bd90-f435ad604aa7","2026-06-26T14:00:27.102Z",{"_type":10,"current":1176},"paging-charity-how-can-engineering-leaders-avoid-becoming-bond-villains","Paging Charity! How can engineering leaders avoid becoming Bond villains?",{"_id":1179,"publishedAt":1180,"slug":1181,"sponsored":85,"title":1183},"4b22c2a3-3779-4966-93eb-5230391dbdce","2026-06-23T14:08:58.595Z",{"_type":10,"current":1182},"your-ai-shipped-a-backend-that-boots-that-is-the-whole-problem","Your AI shipped a backend that boots. That is the whole problem.",{"_id":1185,"publishedAt":1186,"slug":1187,"sponsored":85,"title":1189},"5cf362e1-fe7b-45af-b69c-914731c6a052","2026-06-23T14:00:00.000Z",{"_type":10,"current":1188},"the-2026-developer-survey-is-now-open-for-human-developers-only","The 2026 Developer Survey is now open (for human developers only)!",{"data":1191,"sourceMap":-1},{"count":1192,"lastTimestamp":1193},41,"2023-08-29T09:02:23Z"]