Automating tasks with BASH

From SlackWiki
Jump to navigation Jump to 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.