# How to do a control loop

this is what I figured out in sorting an Array that has already had it's elements declared type int

``````#!/bin/bash
#sorting an "predeclared" array

typeset -i store BigNum
let store=0 BigNum=0

number=([0]=11140344 [1]=3 [2]=0 [3]=2 [4]=11140345 )

for (( a=0; a <= 5 ; a++ ));
do
if (( number[a+1] < number[a] )); then

store=number[\$a]
number[\$a]=number[\$a+1]
number[\$a+1]=\$store
BigNum=\$store

fi

# I think BIGNUM can be passed back in a function by writing
# return \$BIGNUM its passing an array that is the BIG PROBLEM!!!!

echo \$BigNum " BIG NUM always returns the biggest number"
done
``````

this is the FOR LOOP I am working with, it is going way out of bounds.

``````x=0
while [[ \$x -lt 1 ]]; do

# my main loop I am working with
# to get that greatest number
# out of the odd ball numbered
# element put it in order then
# get it LOOP
########
for(( a=0; a<\${#lostsongs[@]}; a++ ));
do

if [[ \${lostsongs[a+1]}<\${lostsongs[a]} ]]; then

store="\${lostsongs[a]}"
lostsongs[a]="\${lostsongs[a+1]}"
lostsongs[a+1]=store
echo "\$store val in if 1st for loop larger val"
fi

# echo \$store " Larger Bigger number post if statement"
let x++
done
#################

let x++
done
``````

this is the output from the good code from my first loop (with set -x).

`````` echo 3 4 1 2 ' all of the array elements filled are in this order'
``````

that is all I am wroking with four(4) elements.

the out put from that loop is this

`````` + echo 'store val in if 1st for loop larger val'
store val in if 1st for loop larger val
+ let x++
+ (( a++  ))
+ (( a<1134 ))
+ [[ '' < store ]]
+ store=store
+ lostsongs[a]=
+ lostsongs[a+1]=store
+ echo 'store val in if 1st for loop larger val'
store val in if 1st for loop larger val
``````

my logical assumption is that

``````(( a<1134 ))
``````

is my array.length when it should be 4, that BASH is seeing causing my for loop to over run and go crazy mad.

All I would like is for someone to help me and write me a control loop to stop my FOR LOOP at the count of 4 as writing all these different types of loops in all the different ways they can be written to try and figure out how to control my FOR LOOP and stop it at 4 is doing noting by driving me loopy.

it would be a great help so I can't quit practicing my arrow up last command Enter then Ctrl C reflexes, and writing every kind of loop known to mankind and get to more important things like learning how to write this BASH syntax in getting that FOR LOOP work too and all that. if that is not out of the question, hopefully it is not. ............................

ADDED DO TO A PERSON ASKING FOR MORE INFORMATION SO THIS IS EVERYTHING-- NOT yelling just caps so one will take notice with out having to add the word SEX.

this first script works what I am working on I want to add it to this script up update the lostsongs array in the

``````#!/bin/bash
#
########################################################################
########################################################################
# for GNU/Linux                                                        #
# BASH Script                                                          #
#                                                                      #
# converts all the mp3 files in a directory from whatever bitrate to   #
# 128k bitrate.                                                        #
# Then adds an underscore between the artist_name_TITLE_ALBUM from the #
# metadata creates a new file of the same, and Directory and           #
# subdirectory in the same manner eleminating the need to use quotes to#
# malnipulate the data and directiories. then moves the new file into  #
# same directories and subdirectories. Then deletes the old file.      #
# ffmpeg only takes it to 192k.                                        #

# You can change it to any bitrate you want (WITHIN_SPECS) and even    #
# add the other -args to include the other features included           #
# with ffmpeg  --    works with version ffmpeg 0.8.9-6:0.8.9-1                         #
# put it in any directory then give it the path  you are working on then run it.
#\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$\$                          #
#&  Written By: Mikie Heras Dec. 04, 2013                              #
#& FINISHED DEC. 5, 2013                    &                          #
#&##########################################&###########################
#&##########################################&###########################

typeset -i xf mf sn bn hn

let xf=1 mf=0 bn=5 hn=6

lostsongs[0]=4

#get MAX NUMBER -- mp3 files in folder
#MAXNUM="\$(ls \$PWD/*.mp3 | wc -l)"

#so it can sit in the home dir and search what ever folder
# I want

MAXNUM="\$(find ~/music/ -type f -name *.mp3 | wc -l )"

mf=MAXNUM #set the count down number

echo ; echo ; echo ; echo ; echo
#inform the user how many files are in the folder

echo \$MAXNUM " mp3's in folder MUSIC"
sleep 3
echo ; echo ; echo ; echo ; echo

#search out all the mp3 files in the directory
# set how many I want to convert at a time

find ~/music/ -type f -name "*.mp3" | while [ \$xf  -le 100  ] ;

#############################################################
#get the metadata tags off the mp3's using exiftool-perl
#################

ARTIST="`exiftool -Artist "\$FILENAME" -p '\$Artist'`"
TITLE="`exiftool -Title  "\$FILENAME" -p '\$Title'`"
ALBUM="`exiftool -Album  "\$FILENAME" -p '\$Album'`"

#replaces all the crap and the spaces
#between the names with an underscore
#"\${x// /_}" meaning "\${varName//search pattern/replace with}"

newArt="\${ARTIST// /_}"
newTit="\${TITLE// /_}"
newAlb="\${ALBUM// /_}"

echo \$newArt
echo \$newTit
echo \$newAlb
#just for good mesure let me see what's going
echo \$FILENAME " before set stipping down.."
sleep 2

#strip the old file name off the path from FILENAME
#over kill but in good measure
c=\$FILENAME
xpath=\${c%/*}
xbase=\${c##*/}
xfext=\${xbase##*.}
xpref=\${xbase%.*}
path=\${xpath}
pref=\${xpref}
ext=\${xfext}

##############################################################
# assign the file a new name
# if LOSTSONG no metadata then add a number to the array[0]
# 1st element [zero] then incurment hn by one 1 for checking to
# be sure that it is the right file in the MOVING FILES section
#
######

if [[ ! -n "\$newArt" && ! -n "\$newTit" && ! -n "\$newAlb" ]] ; then

echo "\${lostsogns[0]} that is Lsogn num.. before going to sogn"
newFile="I_HAVE_NO_IDEA-WHO-I-AM-(Lost-Song-Number-("\${lostsongs[0]}"))-192k.mp3"
(( lostsongs[0]++ ))
let hn++

elif [[ -n "\$newArt" && -n "newTit" && ! -n "\$newAlb" ]] ; then

newFile="Artist-\${newArt}_Title-\${newTit}_192k.mp3"

else

newFile="Artist-\${newArt}_Title-\${newTit}_Album-\${newAlb}_192k.mp3"
fi
echo \$newFile "new file name ..."
sleep 3

##############################################################
# convert the file to 128k using ffmpeg version 0.8.9-6:0.8.9-1
###

ffmpeg  -b 128k -vol 425 -i "\$FILENAME" "\$newFile"

##############################################################
# MAKE DIRs
#############

if [[ ! -d ~/music2 ]] ;then

mkdir ~/music2/
fi

if [[ ! -d ~/music2/"\${newArt}" ]]; then
echo "making newDir \$newArt  ..."
mkdir ~/music2/"\${newArt}"/
fi

if  [[ -d ~/music2/"\${newArt}" && \
! -d ~/music2/"\${newArt}"/"\${newAlb}" ]] ; then
echo "making dir/sub \$newArt / \$newAlb .."
mkdir ~/music2/"\${newArt}"/"\${newAlb}"/
fi

if [[ ! -d ~/music2/lostsongs/ ]] ; then
mkdir ~/music2/lostsongs/
echo "making Lost Dir .."
fi

##################################################################
#
## MOVE THE FILES
#this siganls out the newfile uneekly
#if no counter movement then no lost song was found
#to insure that the \$newFile is one that has a place in a diffetent
#folder named lostsongs "\${foo[0]}" < c && a -gt b
###################################################################

if [[ ! -n "\$ARTIST" && ! -n "\$TITLE" && ! -n "\$ALBUM" ]] ; then
if [[ "\${lostsongs[0]}" < bn && hn > bn   ]] ;
then
echo "Found a Lost Sogn Yo! .."
mv "\${newFile}" ~/music2/lostsongs/
let bn++
fi

fi

## if the newAlb is asigned and not empty
# what to do to check it

if [[ -n "\$newArt" && -n "\${newAlb}" ]] ; then
echo "-n newAlb true -- moving file \
to \$newAlb -- newAlnum \$newArt "
mv -f "\${newFile}" ~/music2/"\${newArt}"/"\${newAlb}"/
fi

if [[ ! -n "\${newAlb}" ]] ; then
echo " -n \$newAlb  newAlbum not present moveing to \$newArt \
new artist.."
mv -f "\${newFile}" ~/music2/"\${newArt}"/
fi

###############################################################
# getrid of the old file
###############################

killfile="\${pref}.\${ext}"
mv "\${path}/\$killfile" "\${killfile//*/killme}"
rm "killme"

############
#
#Used for MAXNUM or checksum in loop to tell script how many files to convert
# in the run
#############
let xf++
let mf--    # lets the user know how many files left to do

echo ; echo ; echo ; echo ; echo ; echo "\$mf ..... mp3/s left to do ..."
echo ; echo ; echo ; echo ; echo
done

# with this new code I am working on to update that lostsongs[0]
# I am having problems with this global asignment too. I googled how to
# make an array global and it seems I am not the only one that has this
# problem - I have yet to find the solution it seems that bash ver has
# a lot to do with it too.
# GNU bash, version 4.2.37(1)-release (i486-pc-linux-gnu)
#
# it is a string val 1 2 3 4 5 6 7 8 9 10 ......
#
# with this a=0 ; a < \$num or \${array[@ ' num'] being a int? ; a++
#
# in C++ it easier all I got a do is, for ( int a ; a < whatever int ; a++ )
#
# if I write it ( \$a ; .. to get to the valule inside that variable I get
# an error too then there is the adding inside the element itself [a+1]
# that I am not  sure if bash can do that even.
#
# when I check this array after I have filled it with just 4 elements
# (for test purposes) outside that first loop I get 0
# BASH don't have a strToint() and IntTostr() that I can find
# to make it easier
#

#!/bin/bash

set -x

typeset -i xf mf sn bn hn n  snewnum d  store

let xf=1 mf=0 bn=3 hn=4 n=1 snewnum=0  store=0 n=0

declare -gA lostsongs  # this does not even work

# declare -a lostsongs # this does not work
# no globalization of array achieved yet

lostnum="\$(find /home/userx/testscripts/ -type f -name "*.mp3" | wc -l)"

###################################################
#
# FOR updating the lost song files so as not to
# over write any
####################################

find /home/userx/testscripts/ -type f -name "*.mp3" | while [[ \$n -lt lostnum ]] ; do

#echo \$FILE  "<-- that is file"
nstring=\${FILE##*/} #gets just the file name
lstring=\${nstring##I*"("} #chops off Lside to the ( leaving num
rstring=\${lstring%%")"*} #chops off Rside to the ) leaving the num

snewnum=\$rstring #holds the char of type num

lostsongs[\$n]=\$snewnum
echo "lostsongs[\$n] = \${lostsongs[n]}  fill array"
echo \${lostsongs[*]} " all the shit"

let n++
done

echo
echo

echo \${#lostsongs[@]}
echo
echo
echo
echo \${lostsongs[*]}

#get the hightest number then pass it
#needs to be  array[0]=greatest number then reset count
#####################

#for(( a=0; a<\${#lostsongs[@]}; a++ ));
#this for does not work because of the -lt synax
#for (( a=0 ; a -lt \${#lostsongs[@]}; a++ ));

for (( a=0 ; a < 4 ; a++ )) ;
do

## Move Larger Values to the right.
# this one don't work
# because there are no spaces around "<", [[ only sees one,
#non-empty, argument, and returns true every time.
# if [[ \${lostsongs[a+1]}<\${lostsongs[a]} ]]; then

# this one works
if [[ \${lostsongs[\$a+1]} -lt \${lostsongs[\$a]} ]]; then

# if (( lostsongs[a+1] < lostsongs[a] )); then
store="\${lostsongs[a]}"
lostsongs[a]="\${lostsongs[\$a+1]}"
echo \${lostsongs[a+1]}
echo "\${lostsongs[a+1]}"
lostsongs[a+1]=\$store
echo "\$store val in if 1st for loop larger val"
fi
``````

# echo \$store " Larger Biger number post if statment"

``````done

##
#with the way that the last "test script is written in this writting this
#is the out put
#
###

userx@bw-crunchbang:~/testscripts\$ ./testnum
+ typeset -i xf mf a sn bn hn n snewnum d store
+ store=0
+ let xf=1 mf=0 bn=3 hn=4 n=1 snewnum=0
+ n=0
+ declare -gA lostsongs
++ wc -l
++ find /home/userx/testscripts/ -type f -name '*.mp3'
+ lostnum=4
+ [[ 0 -lt lostnum ]]
+ find /home/userx/testscripts/ -type f -name '*.mp3'
+ nstring='I_HAVE_NO_IDEA-WHO-I-AM-(Lost-Song-Number-(3))-192k.mp3'
+ lstring='3))-192k.mp3'
+ rstring=3
+ snewnum=3
+ lostsongs[\$n]=3
+ echo 'lostsongs[0] =   fill array'
lostsongs[0] =   fill array
+ echo 3 ' all the shit'
3  all the shit
+ let n++
..............
+ echo 'lostsongs[3] =   fill array'
lostsongs[3] =   fill array
+ echo 3 4 1 2 ' all the shit'
3 4 1 2  all the shit
+ let n++
+ [[ 4 -lt lostnum ]]
+ echo
+ echo 0
0
+ echo

+ (( a=0  ))
+ (( a < 4  ))
+ [[ '' -lt '' ]]
+ (( a++  ))
+ (( a < 4  ))
+ [[ '' -lt '' ]]
+ (( a++  ))
+ (( a < 4  ))
+ [[ '' -lt '' ]]
+ (( a++  ))
+ (( a < 4  ))
+ [[ '' -lt '' ]]
+ (( a++  ))
+ (( a < 4  ))
userx@bw-crunchbang:~/testscripts\$
``````

therefore the first problem is to make that array Global somehow. as I have said Google is full of how do I make an array global with so far I have not found an answer to even the others that asked that question.

the second is turning Char into Int values to work with 'I think that is the two problems I have other then does BASH allow Math in side the element? [a+1] [a*1] (times, x 1) [a/1] div and [a-1] even?

• I added it to this while post everything --- its too much to put in this comment post Dec 12, 2013 at 2:38

This is wrong:

``````    if [[ \${lostsongs[a+1]}<\${lostsongs[a]} ]]; then
``````

because there are no spaces around "<", `[[` only sees one, non-empty, argument, and returns true every time.

You want

``````    if [[ \${lostsongs[a+1]} -lt \${lostsongs[a]} ]]; then
``````

or

``````    if (( lostsongs[a+1] < lostsongs[a] )); then
``````