Search For GIFs Without Leaving Your Terminal
Tags: bash, cli, gif, linux
Published: 2020-12-31 20:48:55

---
title: Search For GIFs Without Leaving Your Terminal
published: yes
description: A CLI utility to help you search for GIFs from the terminal 
tags: bash, cli, gif, linux
//cover_image: https://media.giphy.com/media/Lny6Rw04nsOOc/giphy.gif
---

![terminal](https://media.giphy.com/media/Lny6Rw04nsOOc/giphy.gif)

## Problem

Have you ever wanted to search for GIFs from the terminal?

Perhaps it's just me, but I do a lot in the terminal, from writing code and debugging programs to searching and browsing the web (via [`ddgr`](https://github.com/jarun/ddgr) + [!bangs](https://duckduckgo.com/bang?q=)).

When I am reviewing Pull Requests (via [`gh`](https://github.com/cli/cli) or [`glab`](https://github.com/profclems/glab)), I often like to post a funny GIF as a comment when I'm approving the PR (hopefully to leave the collaborator with a smile).

Initially, I did this by going to a site, like [giphy.com](https://giphy.com), then searching for a GIF, then several clicks later, I got a GIF URL that I can copy/paste into the terminal. This obviously broke my workflow.

## Solution

The second iteration of this used `ddgr`, a command-line interface for DuckDuckGo. Using the `!gif` or `!giphy` [bang](https://duckduckgo.com/bang?) (e.g. `ddgr --no-prompt '!gif yay'`) did save me a few steps as it takes me right to Giphy's search results where I can get a GIF URL with a few clicks. However, because this still requires a browser, it doesn't work for all the times I work on remote development servers (e.g. [GCP Always Free Compute Engine](https://cloud.google.com/free), Raspberry Pi ...etc).

I needed a different solution that was completely in the terminal.

I couldn't find a dependency-free<sup>*</sup> CLI utility that really suit my needs. So, I decided to write a dependency-free CLI utility that allows you to search for GIFs from giphy.com and return a URL.

And it fits in [a tweet](https://twitter.com/petermbenjamin/status/1344680036167688192?s=20). 

Here it is:

```shell
$ giphy() { [ -z "${1}" ] && return 1 || curl -fsSL https://giphy.com/search/${1} | rg -oP "(?<=gifs: ).*?(?=,$)" | jq ".[$(echo $(( $RANDOM % 25 )) )] | .images.original.url" | tr -d '"'; };
```

Let's break it down:

- `[ -z "${1}" ] && return 1 || ...` : this is kind of a ternary operation in Bash. If the 1st argument is empty, then return non-zero exit code, otherwise ...
- `curl -fsSL https://giphy.com/search/${1} `: this is pretty straight-forward. We use `curl` to query the site.
- `rg -oP "(?<=gifs: ).*?(?=,$)"`: this uses Positive Lookbehind (`?<=...`) and Positive Lookahead (`?=...`) Regular Expressions (see [this](https://caspar.bgsu.edu/~courses/Stats/Labs/Handouts/grepadvanced.htm) for more info) to match the text that is between `gifs: ` and `,` at the end of the same line in the HTML response. This is where we have a JSON list of 25 GIFs from the 1st results page.
- `jq ".[$(echo $(( $RANDOM % 25 )) )] | .images.original.url"`: here we use `jq ".[] | .images.original.url"` to parse the JSON list and get at the URL we need. The `$(echo $(( $RANDOM % 25 )) )` is a Bash way of picking a random number between 0 and 25. Another way we could do this is `shuf -i 0-25 -n 1` (see [`shuf`](https://manpage.me/index.cgi?apropos=0&q=shuf&sektion=0&manpath=CentOS+7.1&arch=default&format=html) manual pages for more info).
- `tr -d '"'`: finally, we trim the double-quotes from the URL.

That's it. Now, we can compose this utility with other tools to spread smiles, like `$ gh pr review --approve --comment -b "![yay]($(giphy yay))"` 

## Conclusion

This is why I love the terminal. It gives me the freedom and flexibility to creatively solve a problem and re-use it in composable ways. Check out this [blog post](https://www.expressionsofchange.org/reification-of-interaction/) for additional reading on the merits of CLIs.

I am, by no means, a Bash or Regular Expressions expert and I am sure there are many opportunities for improvement here. So, feel free to leave your ideas, thoughts, suggestions for improvements, or GIFs in the comments section below!

Also, contributions are welcome on the GitHub repo: <https://github.com/pbnj/giphy-cli>

Happy coding!

![wave](https://media.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif)

---

**Footnotes**

<sup>*</sup> My Bash one-liner is not 100% dependency-free. It requires `curl`, [`rg`](https://github.com/BurntSushi/ripgrep) for a consistent grep utility between macOS & Linux, & [`jq`](https://stedolan.github.io/jq/) for command-line JSON parsing. Most GIF CLI utilities I found required system dependencies and entire development toolchains (e.g. `ffmpeg`, `python3`, `dotnet`, ...etc).