Automating tasks with BASH

From SlackWiki
Jump to: navigation, search

Often you will want to automate certain commands with BASH. The easiest way to do this is by using file globbing with wildcards otherwise called expansion. For example say I have a directory with the following files in it

 $ ls
 file1.txt  file2.txt  file3.txt

If I type

 $ ls *.txt
 file1.txt  file2.txt  file3.txt

The Shell will expand *.txt to match any file that matches the pattern of any number of characters followed by a .txt it then sends this list to the ls command. The ls command takes that list as a set and displays the directory listing for each one. Now most commands will work with file globbing but sometimes there are problems. For example if I wish to convert a heap of .jpeg files to 800x600 resolution with one line:

 $ ls *.jpeg
 img_2992.jpeg  img_2994.jpeg  img_2996.jpeg  img_2998.jpeg  img_3000.jpeg  img_3002.jpeg
 img_2993.jpeg  img_2995.jpeg  img_2997.jpeg  img_2999.jpeg  img_3001.jpeg
 $ convert *.jpeg -resize 800x600 *.jpeg
 $ ls *.jpeg
 img_2992.jpeg  img_2998.jpeg   img_3002-10.jpeg  img_3002-16.jpeg  img_3002-3.jpeg  img_3002-9.jpeg
 img_2993.jpeg  img_2999.jpeg   img_3002-11.jpeg  img_3002-17.jpeg  img_3002-4.jpeg  img_3002.jpeg
 img_2994.jpeg  img_3000.jpeg   img_3002-12.jpeg  img_3002-18.jpeg  img_3002-5.jpeg
 img_2995.jpeg  img_3001.jpeg   img_3002-13.jpeg  img_3002-19.jpeg  img_3002-6.jpeg
 img_2996.jpeg  img_3002-0.jpeg  img_3002-14.jpeg  img_3002-2.jpeg   img_3002-7.jpeg
 img_2997.jpeg  img_3002-1.jpeg  img_3002-15.jpeg  img_3002-20.jpeg  img_3002-8.jpeg

Of course that was not what we expected. There is an easier solution to this and that is to use BASH's for loop command.

 $ for var1 in *.jpeg; do convert $var1 -resize 800x600 $var1; done
 $ ls *.jpeg
 img_2992.jpeg  img_2994.jpeg  img_2996.jpeg  img_2998.jpeg  img_3000.jpeg  img_3002.jpeg
 img_2993.jpeg  img_2995.jpeg  img_2997.jpeg  img_2999.jpeg  img_3001.jpeg

What this command does is loop through all the .jpeg files in the directory and for each file it stores the name of that file in the variable $var1 which is then used as two arguments to convert, the input and output file names respectively.

Basically it looks to the system like this

 convert img_2992.jpeg -resize 800x600 img_2992.jpeg
 convert img_2993.jpeg -resize 800x600 img_2993.jpeg
 convert img_2994.jpeg -resize 800x600 img_2994.jpeg
 convert img_2995.jpeg -resize 800x600 img_2995.jpeg
 convert img_2996.jpeg -resize 800x600 img_2996.jpeg
 convert img_2997.jpeg -resize 800x600 img_2997.jpeg
 convert img_2998.jpeg -resize 800x600 img_2998.jpeg
 convert img_2999.jpeg -resize 800x600 img_2999.jpeg
 convert img_3000.jpeg -resize 800x600 img_3000.jpeg
 convert img_3001.jpeg -resize 800x600 img_3001.jpeg
 convert img_3002.jpeg -resize 800x600 img_3002.jpeg

You can play with this by echoing the output of the expansion to the console.

 $ for var2 in *.txt; do echo $var2 ;done
 file1.txt
 file2.txt
 file3.txt
 $ echo *.txt
 file1.txt file2.txt file3.txt

Those are similar expansions but not exactly the same.

Note: var1 and var2 are random variable names that I have picked. You can use other variable names like images or textfiles.