Bash – Array Primer

Posted mostly for my own reference since I always forget the syntax, arrays are invaluable when writing moderately complex shell scripts. If you're writing any serious shell scripts you'll want to refer The Linux Documentation Project's excellent primers: Bash Guide for Beginners and Advanced Bash-Scripting Guide

array.sh

#!/bin/bash
 
echo "<<< Load a file into an array"
echo "# Set the IFS (Internal Field Separator) to a newline
IFS='
'
# Load file.txt from the current directory
arr=( \$( < file.txt ) )
"
 
 
IFS='
'
arr=( $( < file.txt ) )
 
 
echo "<<< Addressing individual array elements"
echo "\${arr[0]} = ${arr[0]}" # the first line of the file
echo "\${arr[1]} = ${arr[1]}" # the second line of the file
 
 
echo ""
echo "<<< \${#VARNAME[@]} will always return the number of elements in an array"
echo "\$arr contains ${#arr[@]} (\${#arr[@]}) items"
 
echo ""
echo "<<< Loop through the array (\${arr[@]}), loading each item as \$foo."
num=1
for foo in "${arr[@]}" ; do
	echo "Loop iteration $num: $foo"
	num=$((num+1))
done
 
 
echo ""
echo "<<< Loop through the array, addressing each item with an index"
num=0
while [[ $num -lt ${#arr[@]} ]] ; do
	echo "Array index $num (\${arr[$num]}): ${arr[$num]}"
	num=$((num+1))
done

file.txt

file line 1
file line 2
file line 3
file line 4

Saving the two files above as array.sh and file.txt, and running array.sh yields:

$./array.sh 
<<< Load a file into an array
# Set the IFS (Internal Field Separator) to a newline
IFS='
'
# Load file.txt from the current directory
arr=( $( < file.txt ) )
 
<<< Addressing individual array elements
${arr[0]} = file line 1
${arr[1]} = file line 2
 
<<< ${#VARNAME[@]} will always return the number of elements in an array
$arr contains 4 (${#arr[@]}) items
 
<<< Loop through the array (${arr[@]}), loading each item as $foo.
Loop iteration 1: file line 1
Loop iteration 2: file line 2
Loop iteration 3: file line 3
Loop iteration 4: file line 4
 
<<< Loop through the array, addressing each item with an index
Array index 0 (${arr[0]}): file line 1
Array index 1 (${arr[1]}): file line 2
Array index 2 (${arr[2]}): file line 3
Array index 3 (${arr[3]}): file line 4

Validate Symlinks on Mac OS X

I'm working on an Folder Action to automatically create some symlinks, and needed to account for a finite number of temporary files, which requires that I know if a symlink is valid or not.

Apple's Developer Tools ships with a utility called GetFileInfo that does just the trick.

/Developer/Tools/GetFileInfo -aa _SYMLINK_ >/dev/null 2>&1 ; echo $?

This will return 0 if the symlink (_SYMLINK_) points to a valid file, and as near as I can tell, 3 if the file does not exist.

Bonus

On Linux you can find the filenames of all broken symlinks in a given directory using find/xargs/grep/sed with

find . -type l -print0 | xargs -0 file | grep "broken symbolic" | sed -e 's/^\|: *broken symbolic.*$/"/g'

The only piece that doesn't work on OS X is the sed regexp (which I'm too lazy to fix), but you can kind of work around that with cut, as long as your symlink filenames don't contain a colon.

find . -type l -print0 | xargs -0 file | grep "broken symbolic" | cut -d':' -f1

© 2007-2012, Corey Gilmore | Posts RSS Feed | Comments RSS Feed | Contact

 

The views expressed on these pages are mine alone and not those of any past or present employer. All information presented on this site was obtained lawfully and not through disclosure under the terms of an NDA.