LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (http://www.linuxquestions.org/questions/linux-software-2/)
-   -   Pipelining data of find command in an array after processing the contents of the data (http://www.linuxquestions.org/questions/linux-software-2/pipelining-data-of-find-command-in-an-array-after-processing-the-contents-of-the-data-812628/)

AshishJogeshwar 06-07-2010 06:04 AM

Pipelining data of find command in an array after processing the contents of the data
 
Hi

I am searching for a file in a specific folder using the following command and storing it in a log file

find . -maxdepth 2 -type f -name "components.xml" -print | while read obj
do
basename `dirname $obj` >> avail_list.log
done


Here i want to do the following
1. Store each entry after processing in an array variable.
2. Use this array variables as arguments to function calls.

Here my primary objective is to store the entries from 'find' command in an array. So it is ok for me if i am not creating the log file.

Regards,
Ashish

druuna 06-07-2010 06:26 AM

Hi,

Don't double/cross post, it is against the LQ rules.

Continue in this thread (disregard, other thread was closed by a mod.)

David the H. 06-07-2010 11:28 AM

Well, it looks like it was the other thread that was closed, so we have to continue here. :)

Anyway, this should be easy enough to do.

Code:

i=0

while read obj; do

    obj="${obj%/*}"
    array[$i]="${obj##*/}"

    echo "${array[$i]}" >> avail_list.log

    let i++

done <<<"$(find . -maxdepth 2 -type f -name "components.xml" -print)"

Assuming bash, I've cleaned things up a little for you.

I've used $(...) instead of `...`.

I replaced basename and dirname with parameter substitution forms. This might cause some problems if there are odd patterns of directory slashes though. You can always simply use array[$i]="$(basename $(dirname $obj))" instead, if necessary, I suppose.

Finally, I've moved the find command to the end using a here string, which is a better position for use in a while loop, and necessary here if you want the variables/array elements to be accessible outside of it.

Note also that gnu find has a -printf option for formatting its output, which could save you a step or two in the above.

By the way, please use [code][/code] tags in the future, to preserve formatting and improve readibility.

AshishJogeshwar 06-08-2010 07:14 AM

Hello David the H.

The solution worked well on my Ubuntu machine having dash, but i faced a different problem when i tried to run it on my target having busybox v1.16.1

And i apologise for my novice mistakes which i made with my post. Hopefully my other threads start on a better note ;-)

my script looks like this now
Code:

switch_app()
{
        dir_name=$1
        echo $1
        echo "entered switch_app"
        xml_file_path=/home/$dir_name
        echo $xml_file_path
        xml_file=$xml_file_path/components.xml
echo $xml_file
        rm ../../usr/bin/components.xml
        ln -s $xml_file ../../usr/bin/components.xml
echo "return from switch_app"
        sync
        return       
}


echo "--------------------------------------"
echo "Available apps are"
echo "--------------------------------------"

i=0
while read obj; do

    obj="${obj%/*}"
    array[$i]="${obj##*/}"

    echo "${array[$i]}"

    let i++

done <<<"$(find . -maxdepth 2 -type f -name "components.xml" -print)"

echo "--------------------------------------"
echo Active topas_app is $active
echo "--------------------------------------"
readlink -f '../usr/bin/components.xml' | while read obj
do
f= basename `dirname $obj`
done
echo "--------------------------------------"
echo
echo "${#array[*]}"
echo "--------------------------------------"
echo "Please enter your choice of topas_app"
echo "--------------------------------------"
for element in $(seq 0 $((${#array[@]} - 1)))
do               
echo "press $element for ${array[$element]}"
done

read entered_val
switch_app ${array[$entered_val]}

And the error is the following
Code:

line 32: syntax error: unexpected redirection
However the links you provided were really helpful in getting my concepts about shell scripting in place :-)

Regards,
Ashish

David the H. 06-08-2010 09:12 AM

Well, that's a different question then, and something you should've mentioned. busybox is a very stripped-down toolset, and likely to not have many of the extensions available in your standard desktop utilities. When your script needs to be portable then you have to be very careful to only use features available on all the systems.

I did a bit of experimenting and some searching, and unfortunately it looks like ash simply doesn't support arrays. You'll have to work out some other way to handle the data. The link above gives a basic workaround, but it isn't exactly pretty.

All the other substitution commands I gave do seem to be supported, however.

I'm not sure I understand all of your code anyway. What's this supposed to do, for example?
Code:

readlink -f '../usr/bin/components.xml' | while read obj
do
f= basename `dirname $obj`
done

First of all, the "f" line is broken, as it uses an embedded command without the proper bracketing (assuming you're actually trying to set a variable here, of course). Also, this is really a variation of what we talked about before, so all my previous comments apply here too. It's using the same while-loop-in-a-pipe subshell I mentioned before, meaning that even if you managed to set f correctly, it wouldn't be available anywhere else in the script (not that I see it being used anywhere else in the script anyway), and basename and dirname can be more efficiently handled with parameter substitutions.

But even more to the point, since there's only one input, the loop itself is completely unnecessary. Just set
f=$(readlink -f ../usr/bin/components.xml).

AshishJogeshwar 06-10-2010 01:52 AM

Hello David the H.

My script looks for an xml file in a folder which is basically a list of all the applications available.
it also specifies the currently active application and then gives the user a choice to select any one app from the ones available.

I used a work around from arrays by piping the data to a temporary log file and then reading the user input for specifying which application is to be selected.

Code:

find . -maxdepth 2 -type f -name "components.xml" -print |
{
        while read obj;
        do
                obj="${obj%/*}"
                obj="${obj##*/}"
                i=$((i+1))
                echo  -e "Press \033[1m $i \033[0m for :-  \033[1m $obj \033[0m"
                echo $obj >> $AVL_APPS
        done
echo "Please select a value"
read entered_val
word=$( cat $AVL_APPS | sed ${entered_val}\!d )
if [ -z "$word" ]
then
echo -e "Wrong Entry :-\033[1m $entered_val \033[0mPlease try again"
else
switch_app $( cat $AVL_APPS | sed ${entered_val}\!d )
fi

This made the script work well :-)

But i thank you specially for all the replies and clarifications you gave on this post.

It is not the output which mattered but what i gained in the process.

Regards,
Ashish


All times are GMT -5. The time now is 01:02 PM.