Making the Shell Less Scary - Starting out

I will fully admit that I grew up comfortable working on a computer without a GUI. From my early days, I had an old computer that I mainly used to play games (some things never change, but current ones don't come on 5 1/4" floppies); in order to get those games to run, I learned from my Mom how to access the correct drive, and the commands to run in order to start up the game.

Today, even though we have fancy GUI apps to do a lot of the work that we need to get done on a daily basis, I still find that it's easier for me to quickly open a terminal window, enter a few commands, and complete whatever task I was doing. Not everything benefits from this approach (imagine doing image editing with a text editor!), but tasks involving finding files, moving files around the system, and working on remote systems works are things that I would much prefer a terminal for.

Today I'm going to dive into a few of the commands that do just the things that I was talking about. These are some of the commands that you would end up using on a day-to-day basis in a terminal window; hopefully I can shine some light on some corners of them that you don't expect.

Directories and Files

Let's say you're an avid photographer - you'll have a lot of photos collected. In order to make sense of your collection, you're going to want to organize those photos. If they were physical photos, you'd want to collect them by the event that you took them at:

Additionally, let's say these photos happened over the course of a few years.

Borrowing from the physical realm, we can place these photos into different folders, or directories, in order to keep them organized. Let's lay them out like so:

You'll notice there are duplicate names here - that's okay, because they're nested within two different folders.

Now, all of these folder names are legit as they stand, but they'll be a little harder to deal with when on the command line with some of the special characters and spaces. It's a standard convention to replace spaces and special characters in names to make it easy to deal with, while retaining most of the meaning that was present in the original names; most of the replacements are things like dashes or underscores. This would be my likely replacement:

Syntactically very similar, and much easier to deal with while typing.

So rather than pulling up a file manager window, let's make this structure out of commands at a terminal.

mkdir makes the dirs

the mkdir command is used to make a directory. The basic invocation is very straightforward:

$ mkdir <folder-name>

This command will create a new directory with the given name based on the directory you're currently in (referred to as your 'Current Working Directory' or 'Present Working Directory'). Sometimes the terminal you're using will tell you where you are as part of the prompt; even if not, you can find out by running the command pwd to give you that directory.

$ pwd
/home/ballpointcarrot

So let's make our photo collection structure:

$ mkdir 2018

Wait... Nothing came back. Did it do anything?

add ls to the list

ls is a versatile command - it gives you a listing of your PWD. This becomes handy when you're looking around you filesystem, and generally know where something is located. If we do an ls where we are now, you'll see something like:

$ ls
2018/   Desktop/        Downloads/      Notes/          Videos/
Books/  Documents/      Music/          Photos/

Oops... that 2018 isn't in the right spot. Let's move it with mv:

$ mv 2018 Photos

Again, we get no output signifying anything. However, on the next ls:

$ ls
Books/          Documents/      Music/  Photos/
Desktop/        Downloads/      Notes/  Videos/

Now we can see that the 2018 folder is no longer here. We want to make sure that it's in the Photos directory though, so we'll check there, too:

Note: this shows that the ls command can be used on folders - meaning you don't have to be in the folder to use ls. That gets handy when you're searching a lot of subfolders.

$ ls Photos
10262018_0001.JPG  10262018_0035.JPG  10262018_0069.JPG  10262018_0103.JPG  10262018_0137.JPG  10262018_0171.JPG  10262018_0205.JPG  10262018_0239.JPG  10262018_0273.JPG  10262018_0307.JPG
10262018_0002.JPG  10262018_0036.JPG  10262018_0070.JPG  10262018_0104.JPG  10262018_0138.JPG  10262018_0172.JPG  10262018_0206.JPG  10262018_0240.JPG  10262018_0274.JPG  10262018_0308.JPG
10262018_0003.JPG  10262018_0037.JPG  10262018_0071.JPG  10262018_0105.JPG  10262018_0139.JPG  10262018_0173.JPG  10262018_0207.JPG  10262018_0241.JPG  10262018_0275.JPG  10262018_0309.JPG
10262018_0004.JPG  10262018_0038.JPG  10262018_0072.JPG  10262018_0106.JPG  10262018_0140.JPG  10262018_0174.JPG  10262018_0208.JPG  10262018_0242.JPG  10262018_0276.JPG  10262018_0310.JPG
...

Whoa! Where's the 2018 folder? These are all just JPG files (the photos that I've been dumping without organizing into the Photos folder). Fortunately, I can filter out the type of object returned from ls:

$ ls -d */
2018//

There's our folder. Now let's explain that command: the -d within the command tells ls that we just want directories, and not files. However, ls isn't smart enough on its own to just grab the directories on its own; we have to explicitly say grab "all directories", which is where */ comes in - it signifies "anything in the current directory" with the asterisk (also called a star or wildcard), and the forward slash is for anything designated a folder.

Let's get to work on the rest of those folders. First, let's put ourselves in the right place.

cd - not just for music

The cd command changes our current working directory. By changing directories, it gives us the ability to change context with what we're doing on the filesystem. In our case, we'll change to the Photos directory, because we're working in the context of organizing our Photos. Makes sense.

$ cd Photos

Again, the command has now output, but we can do a pwd and see that we've changed places:

$ pwd
/home/ballpointcarrot/Photos

Now let's finish up our 2018 folders. Me, being lazy, want to do everything in one shot - fortunately, mkdir lets us do just that:

$ mkdir 2018/joe-wedding 2018/i-heart-food 2018/my-cat

This creates three folders, all nested neatly under the 2018 folder. "Great!", we say, and we go to do 2019:

$ mkdir 2019/tim-bday-bash 2019/vegas-trip 2019/my-cat 2019/i-heart-food
mkdir: cannot create directory ‘2019/tim-bday-bash’: No such file or directory
mkdir: cannot create directory ‘2019/vegas-trip’: No such file or directory
mkdir: cannot create directory ‘2019/my-cat’: No such file or directory
mkdir: cannot create directory ‘2019/i-heart-food’: No such file or directory

Uh oh... because we never created the parent 2019 folder, it's not allowing us to build the rest of the directories. We can outwit it though; mkdir has a parameter option -p, which gives us the ability to make parent directories within the same call:

$ mkdir -p 2019/tim-bday-bash 2019/vegas-trip 2019/my-cat 2019/i-heart-food

All good. Just to double-check:

$ ls 2019
tim-bday-bash/  vegas-trip/     my-cat/         i-heart-food/

Moving the files in

So now we've got our directory structure in the Photos directory, with a boatload of random JPG files. How are we going to get them organized? It looks like a lot of them are around the same dates (look at all the 10262018_xxxx files we have up there). Let's take a look at one or two of them to get a sample, to make sure it's the right event.

Note: This step will be different depending on the platform you're on, so I'll give both.

# OSX example
$ open 10262018_0001.JPG

# Linux example
$ xdg-open 10262018_0001.JPG

Both of these commands do the same thing - they ask the current environment to figure out who the best person to open a JPG file is, and then executes that program. Ideally, you'll see a window with your picture loaded.

miles

Oh look, it's a cat photo. We know where those are supposed to go. I'm going to assume the 300+ photos around this time period are all cat photos (don't judge). We're going go go back to using the mv command. However, instead of individually moving the files one-by-one (which would take forever), we'll make use of our friend the wildcard, and make all of the files move on their own:

$ mv 10262018_* 2018/my-cat

Again, we get nothing back as output, so let's double-check:

$ ls 2018/my-cat
10262018_0001.JPG  10262018_0035.JPG  10262018_0069.JPG  10262018_0103.JPG  10262018_0137.JPG  10262018_0171.JPG  10262018_0205.JPG  10262018_0239.JPG  10262018_0273.JPG  10262018_0307.JPG
10262018_0002.JPG  10262018_0036.JPG  10262018_0070.JPG  10262018_0104.JPG  10262018_0138.JPG  10262018_0172.JPG  10262018_0206.JPG  10262018_0240.JPG  10262018_0274.JPG  10262018_0308.JPG
10262018_0003.JPG  10262018_0037.JPG  10262018_0071.JPG  10262018_0105.JPG  10262018_0139.JPG  10262018_0173.JPG  10262018_0207.JPG  10262018_0241.JPG  10262018_0275.JPG  10262018_0309.JPG
10262018_0004.JPG  10262018_0038.JPG  10262018_0072.JPG  10262018_0106.JPG  10262018_0140.JPG  10262018_0174.JPG  10262018_0208.JPG  10262018_0242.JPG  10262018_0276.JPG  10262018_0310.JPG
...

Great - all our cat photos are now pleasantly sorted.

I'll leave us here for now. I want to make this a continuing series of posts, so please let me know if there's a command that you're interested in. I know that this one may be a little too basic for a lot of dev-types, but hey - everyone has to start somewhere, right? As long as someone makes use of it, I'm happy.

/Beginners/ /Shell/ /Systems/ /Linux/