Twenty-ish Terminal Commands for Getting Around the File System

Recently I was digging around in the terminal and wanted an ls command that behaved like a fully opened tree view. That led me back through a bunch of the file-system commands I use all the time, along with a few switches that make them far more useful.

This is the resulting quick reference. I’m writing this on macOS with zsh, but most of it applies directly to Linux too. A few tools—particularly tree and fd—may need to be installed first.

First, the Many Faces of ls

The plain command lists the current directory.

ls

Add -l for the vertical, long-listing format. This shows permissions, link count, owner, group, size, modified date, and name.

ls -l

Add -a to include hidden entries—names beginning with a dot—and -h to make sizes human-readable. The switches can be combined.

ls -lah

To descend through every directory and list its contents, add -R for recursive.

ls -laRh

That gets us the fully opened contents, although the output is grouped by directory rather than drawn as a visual tree.

Navigation

1. pwd — Where Am I?

When I’ve wandered six directories deep and forgotten where I am, pwd prints the full path to the working directory.

pwd

2. cd — Change Directory

Move into a directory, up one level, back to the previous directory, or straight home.

cd projects
cd ..
cd -
cd ~

Paths containing spaces need quotes, as in cd "My Projects".

3. pushd and popd — Directory Bookmarks, Sort Of

pushd changes directories while saving the current location on a stack. popd takes me back. This is excellent when bouncing between two distant parts of a repository.

pushd ~/Code/my-project/docs
popd

4. tree — The Actual Tree View

Unlike recursive ls, tree draws the hierarchy. -a includes hidden entries, -L 2 limits output to two levels, and -h prints readable sizes.

tree -a -h -L 2

On macOS, install it with brew install tree if it is not already available.

Finding and Inspecting Things

5. find — Search the Directory Tree

Find every Markdown file below the current directory. Here . means “start here,” -type f limits results to files, and -name supplies the filename pattern.

find . -type f -name "*.md"

Use -type d to find directories instead.

6. fd — A Friendlier Find

fd provides a concise, fast alternative when installed. This finds Markdown files while including hidden paths but excluding .git.

fd --hidden --exclude .git '\.md$'

Install it on macOS with brew install fd.

7. stat — All the File Details

stat reports metadata such as size, permissions, timestamps, and inode information.

stat quick-article.md

The exact output differs between macOS and Linux, but the intent is the same.

8. file — What Is This Thing?

Extensions can lie. file inspects the contents and reports what it believes the file actually is.

file mysterious-download

9. du — What Is Using the Space?

du measures disk usage. -s summarizes instead of listing everything below the target, and -h makes the result readable.

du -sh .
du -sh ./*

10. df — How Much Disk Is Left?

Where du examines files and directories, df reports free and used space on mounted file systems. Again, -h keeps the numbers readable.

df -h

11. less — Read Without Flooding the Terminal

For a file longer than one screen, use less. Search with /text, advance with the space bar, move backward with b, and quit with q.

less application.log

12. head and tail — Inspect the Edges

These show the beginning or end of a file. -n 20 asks for twenty lines. tail -f keeps watching as new lines arrive, which is particularly handy for logs.

head -n 20 application.log
tail -n 20 application.log
tail -f application.log

Creating and Managing Files

13. mkdir — Create Directories

The useful switch here is -p: it creates missing parent directories and does not complain if the path already exists.

mkdir -p notes/terminal/examples

14. touch — Create an Empty File

If the file does not exist, touch creates it. If it does exist, touch updates its timestamps without changing the contents.

touch notes.md

15. cp — Copy

Copy a file with plain cp. Use -R to copy a directory recursively and -i to ask before overwriting something.

cp -i notes.md notes-backup.md
cp -Ri source-folder destination-folder

16. mv — Move or Rename

mv handles both jobs. I often include -i for an overwrite prompt.

mv -i draft.md published.md
mv -i published.md archive/

17. ln — Create a Link

ln -s creates a symbolic link. The first path is the existing target; the second is the new link.

ln -s ~/Code/my-project/current-config.json config.json

18. rmdir — Remove an Empty Directory

rmdir only removes empty directories. That limitation makes it useful when I want the command to refuse anything containing files.

rmdir old-empty-folder

19. rm — Remove Files Carefully

Plain rm removes files. -i asks before each removal. Recursive -R removes directories and their contents, so double-check the path before pressing Return.

rm -i unwanted.txt
rm -Ri unwanted-folder

There generally is no built-in undo. On macOS, moving something to the Trash in Finder is often a better choice when I’m not absolutely sure.

20. open — Hand It to macOS

open opens a file in its default application. Give it a directory and Finder opens there; use -a to choose an application.

open README.md
open .
open -a "Visual Studio Code" .

On Linux, the closest general equivalent is usually xdg-open.

A Few Combinations I Actually Use

Here are the quick combinations I tend to reach for most often.

# Everything here, including hidden entries, with readable details.
ls -lah

# Everything below here, recursively, in long format.
ls -laRh

# A manageable visual overview, two levels deep.
tree -a -L 2

# Find the biggest immediate entries in the current directory.
du -sh ./* | sort -h

# Jump somewhere temporarily, inspect it, and jump back.
pushd ~/Code/some-project
ls -lah
popd

That’s the lot: twenty-ish commands and a pile of switches that turn the terminal into a quick file-system navigator. The commands themselves are only half of the story. Run man ls, man find, or man followed by any of the built-in commands above to spelunk through everything else they can do.

‘bash’ A.K.A. The Solution for Everything – Passed Variables & The Script Filename

When writing a script in bash you can pass parameters into that script to work with. For example, let’s say I have a script file called runme.sh and I want to pass in my name and today’s date. I could do that like this.

./runme.sh "Adron Hall" "12/27/2018"

Inside the script I can get access to the parameters by using the bash param variables of $1, $2, and so on. With a little bash code written up like this.

 


echo "The first parameter $1"
echo "The second parameter is $2"
echo "The \$0 parametere returns the name of the file! This file is named $0."

view raw

bashParams.sh

hosted with ❤ by GitHub

dghubble:go-twitter- Go Twitter REST and Streaming API v1.1 2

‘bash’ A.K.A. The Solution for Everything – A few of the *Special Files*!

In bash, the shell reads one or more startup files. Here’s the details about what’s what and which is run when.

  1. /etc/profile is executed automatically at login.
  2. The file from the list of ~/.bash_profile, ~/.bash_login, or ~/.profile are then executed at login.
  3. ~/.bashrc is executed by every non-login shell, but if sh is used to invoke bash it reads the $ENV for POSIX compatability.

For reference, the ~ symbol is used in place of the user directory. One way to check this out yourself is to change directory to ~ with a cd ~ in the shell, then type pwd which will give the current directory. You’ll find that it is something like /Users/adron where instead of my name it’d be your user name.

When invoking the shell, you can also skip the ~/.bashrc or otherwise change the way bash starts up with the following options.

  • bash --init-file theFileToUseInstead or --rcfile instead of ~/.bashrc.
  • bash --norc which is similar to invoking with sh, which will use $ENV.
  • bash --noprofile will prevent /etc/profile or any other personal startup files. This will provide a pretty baseline bash shell for use.

Until next time, happy bash code thrashing!

New Trio of Series: Go, Bash, and Distributed Databases

I’m starting three new series and only making this post now that I’ve got the first round posted and live. Each of these I’ll be back posting so that I have a kind of linked list of blog entries for each of the series. So if you’re into learning Go, I’ve got that going, or you’re into bash hacking, got that too, and of course if you’re digging into distributed systems and databases, I’m tackling that too. It’s kind of the trio of core technologies I’m working on these days, enjoy:

The Nuances of Go – This is going to be a series where I go through some of the details of Go. It’s going to be kind of all over the board, but drill into usage of the language, the why, and what for of various features, capabilities, and related topics.

‘bash’ A.K.A. The Solution for Everything – Bash has been around for a while. But let’s not talk about how old it is, the shell has been used and is being used by about every single operating system on the planet. It’s hugely popular and it isn’t exactly being replaced. You can also basically do anything on a computer that you would want to or need to do with it. However there are lot’s of features and commands one ought to know, this series is going to tackle a new command every new post and go into details of how to use it, what it can be used for, and related tips n’ tricks.

Distributed Database Things to Know – This series is going to cover various features and nuances of the Cassandra distributed database cluster technology. I’ll be diving into a whole host of capabilities, code, and a pointer or three back to white papers when relevant that helped bring these distributed databases into existence.

My goal with each of these is to rise early Monday morning, and time box each article to about 30 minutes. 30 minutes for Go, 30 minutes for bash, and 30 for Cassandra. Then I’ll publish those throughout the week. I set this goal with the hilarious fact that I’m taking time to go record some LinkedIn learning courses on Go and Terraform. With that it might be a week before you see the next trio published. But they’re halfway written already so I might surprise myself. Happy thrashing code!

Documentation First w/ README.md && Project Tree Build

I’m sitting here trying to get the folder structure for my project into a kind of ASCII Tree or something. I wasn’t going to manually do this, it would be insane. Especially on any decent size Enterprise Project with an endless supply of folders and nested content. I went digging to come up with a better solution. On Linux I immediately found the Tree Utility which was perfect.

Except I was on OS-X.

First option I gave a go to was to build the thing. Because I like to do things the hard way sometimes. First I needed to get the source, which is available here.

[sourcecode language=”bash”]curl -O ftp://mama.indstate.edu/linux/tree/tree-1.7.0.tgz[/sourcecode]

Once downloaded, unzip the source into a directory and find the following section for the particular operating system you want to use the utility on. The section for OS settings looked like this when I finished editing it.

[sourcecode language=”bash”]
# Uncomment options below for your particular OS:

# Uncomment for OS X:
CC=cc
CFLAGS=-O2 -Wall -fomit-frame-pointer -no-cpp-precomp
LDFLAGS=
MANDIR=/usr/share/man/man1
OBJS+=strverscmp.o
[/sourcecode]

Now get a good build of the command file.

[sourcecode language=”bash”]
./configure
make
[/sourcecode]

Now let’s get tree into the executable path.

[sourcecode language=”bash”]
sudo mkdir -p /usr/local/bin
sudo cp tree /usr/local/bin/tree
[/sourcecode]

Make sure your ~/.bash_profile is setup right, include this.

[sourcecode language=”bash”]
export PATH="/usr/local/bin:$PATH"
[/sourcecode]

Reload the shell and tree should be available as a command.

The other option which is really simple, if you don’t want to compile to code, is to just use brew to install it.

[sourcecode language=”bash”]
brew install tree
[/sourcecode]

So now you can use tree, and do cool stuff like pipe it out to a file. If you’re running this against a Node.js Project you may want to delete the node_modules directory and then just reinstall it after running the tree command.

[sourcecode language=”bash”]
tree > prof-tree.md
[/sourcecode]

Then in your README.md file you can include the folder structure in the description of the project. Here’s a sample output!

[sourcecode language=”bash”]
.
├── README.md
├── client
│   └── README.md
├── package.json
├── proj-tree.md
├── server
│   ├── boot
│   │   ├── authentication.js
│   │   ├── explorer.js
│   │   ├── rest-api.js
│   │   └── root.js
│   ├── config.json
│   ├── datasources.json
│   ├── middleware.json
│   ├── model-config.json
│   └── server.js
└── test
└── test_exists.js

4 directories, 14 files
[/sourcecode]

That’s a super easy way to offer better documentation that provides some real insight into what various parts of the project structure are actually for.