LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-17-2011, 08:19 PM   #1
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Rep: Reputation: Disabled
BASH scripting Question - Select loop displaying output


...

Last edited by StaffSergeant; 11-21-2011 at 09:05 AM.
 
Old 11-18-2011, 12:31 AM   #2
devUnix
Member
 
Registered: Oct 2010
Posts: 606

Rep: Reputation: 59
Store Output of a Command to an Array

Quote:
Originally Posted by StaffSergeant View Post
Catch is I want to limit it to so only 23 files display at a time so no files scroll off.
Here is the solution:

Code:
#!/bin/bash
FILES=($(ls -1))
Total_Files=${#FILES[@]}
Index=0
Count=0
while [ $Index -lt $Total_Files ];do
        [ $Count -eq 20 ] && { read -p 'Press the Enter/Return Key to Continue...';Count=0; }
        echo $Index : ${FILES[$Index]}
        let 'Index++'
        let 'Count++'
done
exit 0
Remove "$Index : " from the line above not to print the line numbers along with the file names:

Code:
echo ${FILES[$Index]}
Some Notes:

Storing the output of "ls -1" (you can use any other command, say "ls -ltr") command to an array:

Code:
FILES=($(ls -1))
Prompting for an input:

Code:
read -p 'Press the Enter/Return Key to Continue...'
The value is stored to $REPLY and we are simply discarding it; and resetting $Count to 0 (zero). Those two statements are inside { } so that we execute them as a group.

Modify the above script to suit your other requirements.

Cheers!

Last edited by devUnix; 11-18-2011 at 12:43 AM.
 
Old 11-18-2011, 10:23 AM   #3
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
That's a while loop still, I would like it to be a select loop
 
Old 11-18-2011, 12:52 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Quote:
Since you can't use | more
Why not?
 
Old 11-18-2011, 12:57 PM   #5
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
| more does not will not work inside a select loop.
 
Old 11-18-2011, 02:54 PM   #6
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
The reason I want a select loop is because eventually I will be running another select loop with functions in that. So the first select loop above will choose a file from the list, then the second loop will execute a function within side of that such as delete.
 
Old 11-18-2011, 04:06 PM   #7
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by StaffSergeant View Post
The reason I want a select loop is because eventually I will be running another select loop with functions in that. So the first select loop above will choose a file from the list, then the second loop will execute a function within side of that such as delete.
And you cannot do that with if/while?

To make things more complicated, select will print the options in multiple columns at the slightest provocation:

Code:
$ select file in $(seq 1 20); do echo $file; done
1) 1     3) 3    5) 5    7) 7    9) 9   11) 11  13) 13  15) 15  17) 17  19) 19
2) 2     4) 4    6) 6    8) 8   10) 10  12) 12  14) 14  16) 16  18) 18  20) 20
#?
Have you considered dialog? Something like
Code:
dialog --fselect ./ $height $width # will make a nice dialog to select a file
dialog --menu "Select operation:" $height $width $menu_height \
1 "delete" \
2 "move" \
3 "do something else with the file"
I found a nice short tutorial here
 
Old 11-18-2011, 04:26 PM   #8
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
That is what I am working towards something like this:

INPUT1 = $1
INPUT2 = $2
INPUT3 = $3
VAR1 = 0
LENGTH = 0
if [[ INPUT2 == ""]]
then
while [ VAR1 = 0 ];
do
while [ Array.Length > Length ]
do
select VAR1 in Array:Length:Length:+19 "sort name" "sort size" "sort age" "more"
do
case
quit)
exit;;
"sort name") ;;
"sort size") ;;
"sort age") ;;
more) ;;
*)
esac
done
length=legnth+19
done
done
select
do
#commands in a case delete, copy,etc
done

fi
 
Old 11-18-2011, 04:39 PM   #9
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
So I want to use the select loops to be able to select an item off the list (a file) then run another select loop and select an item off that list such as delete etc.
 
Old 11-18-2011, 05:03 PM   #10
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
http://imgly.net/di-PBW3.jpg

This is what I have so far.
 
Old 11-18-2011, 06:38 PM   #11
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
I still don't follow. What is wrong with example given by devUnix? To improve on that, it could look like:
Code:
#!/bin/bash

FILES_PER_SCREEN=20

select_file() {

	# some useful variables
	FILES=($(ls -1)) # breaks if filenames contain spaces
	Total_Files=${#FILES[@]}
	CHOICE1=""

	while [ x"$CHOICE1" = x ]; do
		Index=0
		Count=0

		# print all the files line by line
		while [ $Index -lt $Total_Files ];do

			# if the screen is full wait for the user to either select a file or continue
       		 	[ $Count -eq $FILES_PER_SCREEN ] && {
		       		read -p 'Press the Enter/Return Key to Continue...' CHOICE1;
			       	Count=0;

				# check that the input is an integer
				[ x"$(echo "$CHOICE1"|tr -d [0-9])" = "x" ] || CHOICE1=""

				# if the user selected a file, exit loop
				[ x"$CHOICE1" == "x" ] || break
			}
		        echo $Index : ${FILES[$Index]}
		        let 'Index++'
		        let 'Count++'
		done
	done

	# store the filename in the variable passed as $1
	eval $1=${FILES[$CHOICE1]}
}

select_file FILENAME
echo "Your choice is: $FILENAME"

select OPERATION in delete move copy; do
	[ "$OPERATION" = "delete" ] && rm "$FILENAME"
	# add the code to be done here...
done
exit 0
There is still a lot to improve. The code devUnix wrote for reading the output of ls will not work as expected, if the filenames contain spaces.
 
Old 11-18-2011, 06:54 PM   #12
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
I mean I understand that its easier don't get me wrong. I am just working on an objective where it has to be select loops. I can do it in while loops, it's I am not use to select loops.

We need to prompt the user for a file, then they need to select it, then prompt them for a command to use, and both those need to be select loops. We can nest then in other loops.

Last edited by StaffSergeant; 11-18-2011 at 06:57 PM.
 
Old 11-18-2011, 08:46 PM   #13
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
sigh. Ok, how about something like this then?
Code:
#!/bin/bash

# let's have an array
declare -a FILES 

# this might be a bit strange way to load those names into an array, but it will probably
# deal with the spaces correctly. I don't know if there's a point to this -- it's like 
# 4am and I haven't got a clue about what I'm doing
for file in *; do FILES+=("$file"); done

# some variables --------------------------------------

# Number of files to print at a time
FILES_PER_SCREEN=20

# Number of files to move up and down when user selects
# "previous" or "next"
STEP=20

# our current position in the list -- index of the
# first filename to display
POS=0

# Total number of files in current directory
FILE_NUMBER=${#FILES[@]}

# index of the last filename to display
ENDPOS=$FILES_PER_SCREEN
[[ ENDPOS -ge FILE_NUMBER ]] && (( ENDPOS=$FILE_NUMBER - 1 ))

# Now let's store the entire array of available files in a string
# If there are files behind $ENDPOS, include the 'next' option
OPTIONS=$(for i in $(seq $POS $ENDPOS); do echo "${FILES[$i]}"; done;
	(( ($ENDPOS + 1) < FILE_NUMBER )) && echo "next")

# To check if the user wants to quit the program
QUIT=FALSE

# to treat only newlines as field separators ( so the names
# containing spaces don't break up
IFS='
'

# Main loop ===========================================
# will run until user chooses to quit
while [ x"$QUIT" = xFALSE ]; do
        clear
        # The outer select loop -------------------------------
	select SELECTED in $OPTIONS; do

                # Move down in the list
		if [ x"$SELECTED" = xnext ]; then
       			(( POS = $POS + $STEP ))
			(( ENDPOS = $FILES_PER_SCREEN + $POS ))
			[[ ENDPOS -ge FILE_NUMBER ]] && (( ENDPOS=$FILE_NUMBER - 1 ))
			OPTIONS=$([ "$POS" -gt 0 ] && echo "previous";  for i in $(seq $POS $ENDPOS); do
                                echo "${FILES[$i]}"; done;
				(( ($ENDPOS + 1) < FILE_NUMBER )) && echo "next")
			break
                # Move up in the list
		elif [ x"$SELECTED" = xprevious ]; then
			if [ "$POS" -le "$STEP" ]; then POS=0;
			else (( POS = $POS - $STEP )); fi
			(( ENDPOS = $FILES_PER_SCREEN + $POS ))
			[[ ENDPOS -ge FILE_NUMBER ]] && (( ENDPOS=$FILE_NUMBER - 1 ))
			OPTIONS=$([ "$POS" -gt 0 ] && echo "previous";  for i in $(seq $POS $ENDPOS); do
                                echo "${FILES[$i]}"; done;
				(( ($ENDPOS + 1) < FILE_NUMBER )) && echo "next")
			break
		elif [ x"$SELECTED" = x ]; then
			break;

		else
                        # inner select loop ......................................................
			select OPERATION in delete move quit; do
				if [ x"$OPERATION" = x ]; then continue
				elif [ x"$OPERATION" = xdelete ]; then
					rm "$SELECTED"
				elif [ x"$OPERATION" = xquit ]; then exit 0
				else 
					echo "$OPERATION" # code to be executed
				fi
			done
                        # end of inner select .....................................................
		fi

	done
        # end of outer select ----------------------------------------------

done
# end of main loop ===============================================
There still is the problem of select using multiple columns sometimes, so there's no easy way to know how many lines will it take. But it shouldn't be more than about 23 as long as there's no line wrapping.
Another problem would be if there happened to be files named "previous" or "next" in the current directory.
But I'll leave that to you to deal with as an exercise :P

Last edited by millgates; 11-18-2011 at 09:14 PM. Reason: adding comments
 
Old 11-19-2011, 10:23 PM   #14
StaffSergeant
LQ Newbie
 
Registered: Nov 2011
Posts: 18

Original Poster
Rep: Reputation: Disabled
I am currently on 2 day order with my Army Unit, havn't had to look at it, just printed it and going to look at it at chow.

Thanks for the help though!
 
Old 11-20-2011, 11:57 PM   #15
devUnix
Member
 
Registered: Oct 2010
Posts: 606

Rep: Reputation: 59
Quote:
Originally Posted by StaffSergeant View Post
That's a while loop still, I would like it to be a select loop
Put embed that while loop in your select select statements.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
bash to loop thorouh mysql select array z01krh Programming 3 12-27-2017 08:30 PM
Bash Loop Scripting question TwinReverb Programming 2 10-21-2011 05:24 AM
[SOLVED] Bash Scripting (until loop) cryingthug Programming 10 06-30-2010 09:30 PM
Need help in bash scripting in while loop manya Programming 2 11-25-2009 09:51 AM
BASH Need help figuring out how to loop SELECT statement mcdrr Programming 2 05-08-2007 04:47 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

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

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration