Skip to content

Terminal: It’s a Wild Batch

The real power of the command line comes from the ability to work on your data in batch. We already saw the * character as the wildcard. It will match anything and everything. For example if we were to look for a file and only remembered the first letter of it we could write:

a*

This would match every file starting with “a”.

a*b.*

would match any file that starts with “a” and ends with “b” and has any kind of extension. So let’s try this on a large number of files:

mkdir lotOfFiles
cd lotsOfFiles
touch empty{1..100}.txt
ls

touchALot

As you can see, we created s new folder, moved into it and used the touch command to create files. The {} are a nice feature of bash which will expand to the equivalent of:

touch empty1.txt empty2.txt empty3.txt empty4.txt ... empty100.txt
touchLots_ls

This is called bracket extension and can be very handy.

So now we have a hundred files numbered from 1-100. We already know that we can delete them all by writing:

rm *

or

rm *.txt

If we want to be careful to only delete text files in the pwd. Let’s try and remove all files that have a “1” in them:

rm *1*.txtrm_all1

This will delete any .txt file that contains a “1” anywhere in the filename.

There are a number of other wildcard options:

?      will match any one character in contrast to any character in the *

ls empty?0.txtwildcards1

This convenient way of using the ls command lets you filter the output a little bit. Here we want to see all files the have a two digit number in it.

[]      specify a range of options (logical OR)

ls empty[1-5].txt

ls_filter2

[!]      is the logical NOT operator and matches except what is in between the brackets.

ls empty[!5].txt

ls_filter1

Ignore any filename with a “5” in it.

 

 

Here is a simple case example of how I use these commands to do some automated cleanup when things get messy. My Desktop (and Download folder for that matter) start out pretty clean at the beginning of the school year. However, they get cluttered pretty quickly to a point where I can’t find anything anymore. So I decided to write this little script (we will look at scripting later). If you are used to other programming languages, the if statement looks a little bit odd and takes some getting used to. I won’t go into it now and might do another post in the future. Here is the script:

It comes in two parts. First I will show you the heart of it:

#move all files of type $1 to a folder in the same location named $1_repo
_MRrepo () {

if [ $# -eq 1 ]; then

local _folder=repo_$1

mkdir -pv $_folder

mv *.$1 $_folder/

fi

if [ $# -eq 2 ]; then

local _folder=repo_$2

mkdir -pv $_folder

mv *.$1 $_folder/

fi

}

What is going on here:

The # character means that Terminal will ignore any text that follows on this line. This is used a lot to add comments to the code that explains how it works, what variables it is expecting, etc. The if statement checks if we have exactly one argument supplied to the script ($# denotes all arguments that where entered in terminal). We then grab that argument with $1. This represents the extension of the file we want to move. Next we create a local variable with the name of the folder we want to move our files to called “repo_” with the added extension.

 

And here is the second part where the logic is set up:

#move a number of different file types to their respective repo folders
MRclean() {

for file in *
do
if [[ -f $file ]]; then
case $file in
#######################################
*.zip) _MRrepo zip;;
*.tar.bz2) _MRrepo tar.bz2 zip;;
*.tar.gz) _MRrepo tar.gz zip;;
*.bz2) _MRrepo bz2 zip;;
*.rar) _MRrepo rar zip;;
*.gz) _MRrepo gz zip;;
*.tar) _MRrepo tar zip;;
*.tbz2) _MRrepo tbz2 zip;;
*.tgz) _MRrepo tgz zip;;
*.Z) _MRrepo Z zip;;
*.7z) _MRrepo 7z zip;;
*.dmg) _MRrepo dmg zip;;
*.iso) _MRrepo iso zip;;
#######################################
*.mp3) _MRrepo mp3 sound;;
*.aif) _MRrepo aif sound;;
*.aiff) _MRrepo aiff sound;;
*.wav) _MRrepo wav sound;;
#######################################
*.mp4) _MRrepo mp4 movie;;
*.mov) _MRrepo mov movie;;
*.MOV) _MRrepo MOV movie;;
*.m4v) _MRrepo m4v movie;;
#######################################
*.jpg) _MRrepo jpg pics;;
*.JPG) _MRrepo JPG pics;;
*.png) _MRrepo png pics;;
*.PNG) _MRrepo PNG pics;;
*.tiff) _MRrepo tiff pics;;
*.tif) _MRrepo tif pics;;
*.bmp) _MRrepo bmp pics;;
*.svg) _MRrepo svg pics;;
*.pict) _MRrepo pict pics;;
*.pct) _MRrepo pct pics;;
#######################################
*.ppt) _MRrepo ppt;;
*.pptx) _MRrepo pptx ppt;;
*.key) _MRrepo key ppt;;
#######################################
*.m) _MRrepo m code;;
*.playground) _MRrepo playground code;;
*.c) _MRrepo c code;;
*.js) _MRrepo js code;;
*.h) _MRrepo h code;;
*.rb) _MRrepo rb code;;
#######################################
*.doc) _MRrepo doc docx;;
*.docx) _MRrepo docx;;
*.dot) _MRrepo dot docx;;
*.dotx) _MRrepo dotx docx;;
#######################################
*.txt) _MRrepo txt;;
*.rtf) _MRrepo rtf txt;;
*.csv) _MRrepo csv txt;;
#######################################
*.maxpat) _MRrepo maxpat max;;
*.maxhelp) _MRrepo maxhelp max;;
*.maxpresets) _MRrepo maxpresets max;;
#######################################
*.na) _MRrepo na score;;
*.mus) _MRrepo mus score;;
*.MUS) _MRrepo MUS score;;
#######################################
*.html) _MRrepo html web;;
*.eml) _MRrepo eml web;;
*.webloc) _MRrepo webloc web;;
#######################################
*.pdf) _MRrepo pdf;;
*.PDF) _MRrepo PDF pdf;;
*.eps) _MRrepo eps pdf;;
*.ps) _MRrepo ps pdf;;
*) echo "no match for `$file`";;
esac

fi
done

lc

}


Btw. lc is an alias I have set up in my .bash_profile as we have seen in a previous post. We are using the wildcard * to match for filetypes. Then we send that filetype to _MRrepo for the actual cleanup work…

Both _MRrepo and MRclean are inside of the .bash_profile right now but should probably be made dedicated scripts. A script is a text file that the terminal recognizes as executable, which means we need to modify the permissions of a text file. By the time we are done, the file icon should have changed to something like this:ExecutableBinaryIcon

We need to copy the above text into new text files and save them. In order for Terminal to know which flavour of scripting to use we have to add this as the first line in our text file:

#! /bin/bash

To change any text file to executable use:

chmod +x <file path>

If your file is in a search path of terminal, you can now use it like any other command we already know. So in my case I would write (assuming my text files are in my pwd):

chmod +x _MRrepo
chmod +x MRclean

After deleting the corresponding bits in .bash_profile we are ready to use our new scripts.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.