handy cli commands

Sometimes, I need to get a computer to do something, and that's when I engage the weak and perpetually terrified part of my brain that is in charge of computer code. I get myself into the weirdest situations calling for the most specific, once-in-a-lifetime strings of code - below, you'll find some I've needed so far. Some of it is damn basic, stemming from the time I was new to the commandline, but I'm leaving it all on this page as someone who is where I used to be may come across it.

It all works in Linux, which means most of it will work in Apple systems. Microsoft is working on a complete terminal emulator for Windows that actually works - good for them.

apply command to multiple files

If you have a command that you wish to apply to multiple files (for instance, all files in a directory) you can toss it into a for loop.
some command file.txt
ends up looking like
for f in *.*; do some command "$f"; done
In which some command is executed for all files in the directory. "$f" means the filename (without extension). *.* refers to the files in the directory; you can replace the asterisks with strings to be more precise (*.txt to target only text files, et cetera).

replace string in filename

This example replaces any occurrence of foo with bar in the filename of every file in the working directory.
rename 's/foo/bar/g' *
This is just the intended use of rename; however, forumdwellers will often give such convoluted ways of doing something that can be done with rename that I think it's useful to give this example.

Remember to \escape symbols like ., # or !. To preview the result without renaming, add -n directly after rename. When you're happy with the result, remove the -n and execute.

remove preceding 0s from filename

The example removes the preceding zeroes from all JPEG files in the working directory.
rename 's/^0*//' *.jpg

rename files from a list

Pop into a spreadsheet editor and make a file (rename.txt) with a list of filenames looking like so:
oldname1.ext newname1.ext
oldname2.ext newname2.ext
oldname3.ext newname3.ext
Et cetera. the filenames are separated by spaces and must include the extensions. If you have filenames with spaces in them, place the entire filename in "quotes". Place the file in your working directory and run this line of code:
while read line; do eval mv $line; done < rename.txt
It simply appends mv to the start of each line, and then runs them.

copy first lines from text files

This example takes all first lines from every file in the working directory that ends in .txt and puts those lines in newfile.txt.
head -n1 *.txt > newfile.txt

replace string with filename

This example replaces every occurence of the string 'foo' with the filename of the file it occurs in. It's a bit more code; it's best to just make it into a runnable batch file, so that's how I've formatted it.
for f in *.txt
 name=$(basename "$file")
 sed -i -e "s/foo/$namex/g" $name

remove lines without string

This example removes any line in file.txt that does not contain the string 'foo'.
sed -n -i '/foo/p' file.txt

compress video for the web

This example converts any video in the working directory to a 640px wide WebM with ~128k audio. If you have a file called video.avi, it will output it as video_out.webm in the working directory.
for f in *.*; do ffmpeg -i "$f" -vf scale=640:ih*640/iw -vcodec libvpx -b:v 0.4M -acodec libvorbis -qscale:a 5 oot/"$f".webm; done
I've found that these settings are good for web video (see here): small files with decent resolution and audio. You can experiment with them to see what suits you best, of course.

compress PDFs

Image-laden PDFs can end up being quite large, and unless you have the source from which the PDF is created, there is no readily apparent way to shrink it. The key is to compress embedded images whilst preserving text, for which we use GhostScript utilising pdfwrite

This example converts in.pdf to out.pdf, compressing its embedded images to what it considers 'ebook' levels; decent but not beautiful.

gs -sDEVICE=pdfwrite -dNOPAUSE -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dBATCH -sOutputFile=out.pdf in.pdf
The controls aren't terribly fine-grained, but it's good enough for most purposes. Other options for the -DPDFSETTINGS flag are /screen (shit), /printer (a bit better than ebook), /prepress (nice) and /default (the best). GhostScript is great, but its flags' freaky capitalisation is a fucking nightmare.