Bash 2 dimensional array
Hi, I have this small problem with a bash script:
#!/bin/bash echo "start full backup" if [ ! -d /mnt/hdb/bu ]; then echo "creating new backup folder" mkdir /mnt/hdb/bu fi touch /mnt/hdb/bu/bulogerr.txt #always make sure that you make a safe copy of the previous full backup #so you can always fall back on the full bu of last week. BUFILES="/mnt/hdb/bu/etc_all.tar /mnt/hdb/bu/var_all.tar /mnt/hdb/bu/home_all.tar /mnt/hdb/bu/root_all.tar /mnt/hdb/bu/apache2_all.tar /mnt/hdb/bu/mysqldb_all.tar" for fl in $BUFILES; do echo -n "compressing previous $fl using gzip... " if [ -f $fl ]; then gzip -f -S .gz $fl >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt if [ "$?" -eq 0 ]; then rm $fl >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt echo "sucess" else echo "failed: could not gzip $fl" fi else echo "failed: $fl could not be found" fi done FILES="/etc /mnt/hdb/bu/etc_all.tar /var /mnt/hdb/bu/var_all.tar /home /mnt/hdb/bu/home_all.tar /root /mnt/hdb/bu/root_all.tar /usr/local/apache2 /mnt/hdb/bu/apache2_all.tar /usr/local/mysql/var /mnt/hdb/bu/mysqldb_all.tar" for fl in $FILES; do set -- $fl echo -n "backup $1 with tar... " tar cvf $2 $1 >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt if [ "$?" -eq 0 ]; then echo "sucess" else echo "failed: see bulogerr.txt for details" fi done echo "backup done" exit 0 the first part where I compress the .tar files works out just fine but the second part where I create the .tar files doesn't work at all. I get the following output: start full backup backup /etc with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/etc_all.tar with tar... failed: see bulogerr.txt for details backup /var with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/var_all.tar with tar... failed: see bulogerr.txt for details backup /home with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/home_all.tar with tar... failed: see bulogerr.txt for details backup /root with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/root_all.tar with tar... failed: see bulogerr.txt for details backup /usr/local/apache2 with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/apache2_all.tar with tar... failed: see bulogerr.txt for details backup /usr/local/mysql/var with tar... failed: see bulogerr.txt for details backup /mnt/hdb/bu/mysqldb_all.tar with tar... failed: see bulogerr.txt for details backup done => Instead of executing the "tar cvf $2 $1 >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt" command with both the variables, it looks like he tries it with each one at a time: I want: tar cvf /mnt/hdb/bu/etc_all.tar /etc >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt but all I seem to get is: tar cvf /etc >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt or: tar cvf /mnt/hdb/bu/etc_all.tar >/dev/null 2>>/mnt/hdb/bu/bulogerr.txt I was looking for 2dim arrays but they look quite impossible in bash... Thanks if someone can help me out or point me in the right direction here. kind regards, Lieven |
Ok, just made two one dimensional arrays with the same index, made it look like:
X=6 f[1]=/mnt/hdb/bu/etc_all.tar f[2]=/mnt/hdb/bu/var_all.tar f[3]=/mnt/hdb/bu/home_all.tar f[4]=/mnt/hdb/bu/root_all.tar f[5]=/mnt/hdb/bu/apache2_all.tar f[6]=/mnt/hdb/bu/mysqldb_all.tar d[1]=/etc d[2]=/var d[3]=/home d[4]=/root d[5]=/usr/local/apache2 d[6]=/usr/local/mysql/var i=0 while [ "$i" -lt "$X" ] do let "i++" echo "file: ${f[$i]} directory: ${d[$i]}" done => output looks ok now. Why-o-why are there no multi-dimensional arrays in bash? |
You could simplify the problem by creating a map for the 6,
* etc -> /etc * var -> /var ... * mysql -> /usr/local/mysql/var You could just set "etc=/etc" and so on, and get the directory using Code:
eval dir=$`echo $fl` And then you could have a 1d loop over "etc var home root apache2 mysqldb". But you asked for a bash solution with a 2D array. You can separate the two values that belong together with a comma, and change the following part of your original script: Code:
FILES="/etc,/mnt/hdb/bu/etc_all.tar |
Ok, so I understand that tr can split a variable using a delimiter you can choose freely.
But I still don't understand why simply set -- $fl didn't work. I tested it on the shell: var="abc def" set -- $var echo $1 #output: abc echo $2 #output: def => why doesn't it work in the loop? regards, Lieven |
The command tr "translates", hence the name. E.g., 'tr abc xyz' will replace every occurrence of a with x, of b with y, and of c with z. See 'man tr' for more. So tr doesn't officially "split" a variable -- it's bash's choice to take whitespace as separator (but not, e.g., comma, slash, letters).
The original loop didn't do what you expected because the list $FILES had 12 words, each of which was assigned to fl, one at a time. Both space and newline are whitespace, and equally separate words. By using commas instead of spaces, I changed that to 6 words. That said, my preferred solution would still avoid 2D arrays: Code:
etc=/etc |
Thanks for the explanation.
Altough I'm sure that the solution I tried at first works (2d table), yours looks more elegant. kind regards, Lieven |
All times are GMT -5. The time now is 09:15 PM. |