Skip Navigation

Advanced Terminal Tips and Tricks

www.bitsand.cloud Advanced Terminal Tips and Tricks

When I was first starting out in software engineering, it felt like there was a never-ending barrage of tooling to learn. After more than a decade in CLI environments, I still find myself constantly learning new features and fun facts - but it’s fairly rare that I learn something new that I end up u...

21 comments
  • My favorite tips are:

    You can filter the output of a command. Most commands return parameters like (output, error) so you can filter them by number like 1>/dev/null will filter the output and only show the errors, and 2>/dev/null will filter the errors and only show the output. Also if you want a command to run silently but it doesn't have it's own built-in quiet mode you can add &>/dev/null which will filter everything.

    Bash (and other shell's I assume) can be fully customized. In addition to the .bashrc file in your home directory, there are also a few common files that bash will look for like .bash_aliases, .bash_commands, .bash_profile or you can create your own and just add to the end of the .bashrc file ./YOUR_CUSTOM_BASH_FILE_NAME

    Inside that file you can add any custom commands you want to run for every bash shell like aliases and what not.

    I personally often use a simple update command like so alias up='sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y' which just makes running updates, upgrades, and clean-up so much easier. Just type up and enter your password. I have previously added in things like &>/dev/null to quiet the commands and echo Fetching updates... to make some commands quieter but still give some simple feedback.

    There's also the basics of moving around a terminal command as others have pointed out. The easiest and the one I use the most is if you hold CTRL+LEFT_ARROW the cursor will move entire words instead of one character at a time. Very helpful if you need to change something in the middle of a command.

  • You can use - everywhere you can use a ref in a git command. I very often use

     undefined
        
    git checkout master
    git pull
    git checkout -
    git merge -
    
      

    (Of course that’s all aliased and I have other flags in there too, but that’s the gist)

    • Same for cd -. Nice if you want to go to /etc/blah, and then back to where you were.

      You can also use pushd and popd which will push and pop directories from a stack, if you need to do something more complex.

      Also, if you want to switch faster between branches, slap this in your ~/.gitconfig under [alias]:

      co = !git checkout $(git for-each-ref refs/heads/ --format='%(refname:short)' | fzf)

      Presuming you've got fzf installed, you can now git co (co = checkout) to get a menu with fuzzy find capabilities to switch between branches. Nice if branch names are long/similar/only-different-at-the-end.

      fzf is dope.

      • I have fzf-git for all of that, but honestly I don't ever use it, as I'm hardly ever switching between branches and tab complete is enough for me in most cases.

         undefined
            
        ###
        # FZF GIT
        ###
        # Deciphered from fzf-file-widget. Somewhat unclear why it doesn't exist already!
        function fzf_add_to_commandline -d 'add stdin to the command line, for fzf functions'
          #git checkout $1
          read -l result
          
          commandline -t ""
          commandline -it -- (string escape $result)
          commandline -f repaint
        end
        
        function fzf_checkout -d "git checkout"
          read -l result
          git checkout $result
        end
        
        
        # https://gist.github.com/aluxian/9c6f97557b7971c32fdff2f2b1da8209
        function __git_fzf_is_in_git_repo
          command -s -q git
            and git rev-parse HEAD >/dev/null 2>&1
        end
        
        function __git_fzf_git_status
          __git_fzf_is_in_git_repo; or return
          git -c color.status=always status --short | \
            fzf -m --ansi --preview 'git diff --color=always HEAD -- {-1} | head -500' | \
            cut -c4- | \
            sed 's/.* -> //' | \
            fzf_add_to_commandline
          commandline -f repaint
        end
        
        function __git_fzf_git_branch
          __git_fzf_is_in_git_repo; or return
          git branch -a --color=always | \
            grep -v '/HEAD\s' | \
            fzf -m --ansi --preview-window right:70% --preview 'git log --color=always --oneline --graph --date=short \
              --pretty="format:%C(auto)%cd %h%d %s %C(magenta)[%an]%Creset" \
              --print0 \
              --read0 \
              (echo {} | sed s/^..// | cut -d" " -f1) | head -'$LINES | \
            sed 's/^..//' | cut -d' ' -f1 | \
            sed 's#^remotes/##' | \
            # fzf_add_to_commandline | \
            fzf_checkout
        end
        
        function __git_fzf_git_tag
          __git_fzf_is_in_git_repo; or return
          git tag --sort -version:refname | \
            fzf -m --ansi --preview-window right:70% --preview 'git show --color=always {} | head -'$LINES | \
            fzf_add_to_commandline
        
        end
        
        function __git_fzf_git_log
          __git_fzf_is_in_git_repo; or return
          git log --color=always --graph --date=short --format="%C(auto)%cd %h%d %s %C(magenta)[%an]%Creset" | \
            fzf -m --ansi --reverse --preview 'git show --color=always (echo {} | grep -o "[a-f0-9]\{7,\}") | head -'$LINES | \
            sed -E 's/.*([a-f0-9]{7,}).*/\1/' | \
            fzf_add_to_commandline
        end
        
        # https://gist.github.com/junegunn/8b572b8d4b5eddd8b85e5f4d40f17236
        function git_fzf_key_bindings -d "Set custom key bindings for git+fzf"
          bind \ca\cs __git_fzf_git_status
          bind \ca\cf __git_fzf_git_branch
          bind \ca\ct __git_fzf_git_tag
          bind \ca\cl __git_fzf_git_log
        end
        
        git_fzf_key_bindings
        
          
21 comments