LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Bash indirect reference to array variable(s) (https://www.linuxquestions.org/questions/programming-9/bash-indirect-reference-to-array-variable-s-493223/)

sixerjman 10-17-2006 12:31 PM

Bash indirect reference to array variable(s)
 
I'm trying to programmatically create and reference arrays which
are based on the files in a directory. The arrays are created using
a 'for' loop, that's not a problem. The difficulty arises in referencing each array after creation. I tried creating a separate file which contains the file names, then accessing each array by filename (either directly or indirectly), but niether is working.

Consider:

Code:

for fname in *
do
    fnamearray[$index]=$fname
    stat -c %n,%U,%x,%y $fname > $TEMPFILE
    fnamen=$(awk -F"," '{ print $1 }' $TEMPFILE)      # File name
    fnameu=$(awk -F"," '{ print $2 }' $TEMPFILE)      # User name
    fname=$(awk -F"," '{ print $3 }' $TEMPFILE)        # Access time
    fname[3]=$(awk -F"," '{ print $4 }' $TEMPFILE)    # Modification time
    let 'index+=1'
    echo ${fnamearray[$index]} >> $TEMPFILE2
done

echo ${fnamearray[0]}                                  # 1st file name
echo $(!fnamearray[1])                                  # Should be element 1 (user name)?

Maybe what I'm trying to do is not yet implemented in Bash? If not,
what is the proper syntax/construction to dereference an array variable indirectly?

bigearsbilly 10-18-2006 09:01 AM

you may find this idiom a bit cleaner rather than all that
awk tempfile nonsense.
(I am using date, as no 'stat' on solaris)

you can use set to extrapolate to the numbered parameters

Code:

$ date
Wednesday October 18 14:57:28 BST 2006


$ set -- $(date)
$ echo $*
Wednesday October 18 14:57:39 BST 2006

# let's reverse it!
$ echo $6 $5 $4 $3 $2 $1
2006 BST 14:57:39 18 October Wednesday


ygloo 10-18-2006 01:53 PM

what is "!" for

echo $(!fnamearray[1]) # Should be element 1 (user name)?

sixerjman 10-25-2006 10:07 AM

THANK YOU! Yes, the awk/TEMPFILE is ugly and unnecessary, but it was my first try at the script and I was stuck. I always have the feeling that the more ugly and unwieldy the code I'm writing is, the more likely there's a much easier way to do it. Thanks again! :-D

bigearsbilly 10-25-2006 10:23 AM

very very true.
uglyness is KEY.

If my code starts getting ugly, or complicated I seriously
think about re-doing it.

It's a cool technique the set, very few people know of it.
remember that set technique will clobber your existing parameters
unless you put in a function or a subshell,

try this to show your PATH:
Code:


(IFS=:;set -- $PATH;for x;do echo $x;done)


sixerjman 10-25-2006 11:02 AM

ygloo, the "!" notation in that context is an attempt to indirectly reference a variable via the contents of another variable. I solved the problem by abandoning the indirect variable stuff and just assigning a unique variable for each file name called "$fname.stat" in the "for" loop.

jschiwal 10-25-2006 11:18 AM

I made some minor corrections to your original script:
Code:

TEMPFILE=tempfile
TEMPFILE2=tempfile2
for fname in *
do
    fnamearray[$index]=$fname
    stat -c %n,%U,%x,%y "$fname" > $TEMPFILE
    fnamen=$(awk -F"," '{ print $1 }' $TEMPFILE)      # File name
    fnameu=$(awk -F"," '{ print $2 }' $TEMPFILE)      # User name
    fname=$(awk -F"," '{ print $3 }' $TEMPFILE)        # Access time
    fname[3]=$(awk -F"," '{ print $4 }' $TEMPFILE)    # Modification time
    let 'index+=1'
    echo ${fnamearray[$index]} >> $TEMPFILE2
done

echo ${fnamearray[0]}                                  # 1st file name
echo "${!fnamearray[1]}"                                # Should be element 1 (user name)?

But I don't understand what you are trying to to in the last line. Suppose that ${fnamearray[1] is "poodle.jpg".
The indirection will expand to "echo ${poodle.jpg}".

----

To create an array of the files in the current directory you could do something like this:
Code:

fnamearray=($(find ./ -maxdepth 1 -type f -printf "%f "))


All times are GMT -5. The time now is 03:48 PM.