You are not logged in.

#1 2018-04-13 18:18:40

awesomepilot
Member
Registered: 2012-09-28
Posts: 18

[SOLVED] Trying to use an f for loop, but its not working right.

Hey peeps!  I'm writing a shell script device formatter.  My vision of what i want it to do is; get an array of devices on the machine, then print that array to the user with each  device labeled by number (ex 1./dev/sda 2./dev/sdb etc).  Then it will ask the user what drive to format then it will use some format program like fdisk or parted.  But I'm having trouble listing out the devs in a numbered format.

Here is my code.

#!/bin/bash
# DONE::TODO: Figure out how to create a for loop array that detects and records all block devices and partitions.
# TODO: Figure out how to echo a dynamic list of devices unique to the machine.

echo "############################";
echo "# Welcome to mkparts 0.0.1      #";
echo "############################";

# Create empty device array
declare -a arrPics

# Get devs in /dev
for file in /dev/sd*;
do
    arrPics=("${arrPics[@]}" "$file")   # Add devs to array.
done

# Show a dynamic menu with label numbers for each devs
for i in $arrPics;do
  NUMBER_OF_DEVICES_STRING=${#arrPics[@]};   # Was thinking that this is returning a string or something?
  NUMBER_OF_DEVICES=$NUMBER_OF_DEVICES_STRING;  # DIdn't work

  for i in {1..$NUMBER_OF_DEVICES};do
    echo $i
  done
done

So the result of this code is "{1..6}" instead of counting 1 throught 6.
I wan't it to count from one to six and then I can incorperate that into my list of devices, but I just can't get it to iterate.  Now if I replace the "$NUMBER_OF_DEVICES" with just 6, it works.  But then it will be a static list.   Any input is appreciated!  Thanks.

Last edited by awesomepilot (2018-04-13 19:59:31)

Offline

#2 2018-04-13 18:27:52

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

First, To append to an array just do `arrPix+=("$file")`.

Second, on the "show menu" loop, what is `for i in $arrPics` supposed to do?  You are treating an array like a simple variable.  You may mean, `for i in ${arrPics[@]}` if you want to loop through the entries, or perhaps `for i in $(seq 1 ${#arrPics[@]})` if you want the index of each entry.  As for that inner loop, I have no idea what that is all about.

Also note that shell variables don't have types, they are just their content.

On a higher level note, you probably don't want to match `sd*`, but `sd?`

There's also no need to construct a list then loop through the list - just do them both at once:

#!/bin/bash

find /dev/ -name 'sd?' | while read device; do
    printf '%d. %s\n' $((++i)) $device
    arrPics+=($device)
done
# ... go on to get user's choice here

Finally, rather than reinventing the wheel, you may want to check out bash's `select` to generate this menu for you.

Last edited by Trilby (2018-04-13 18:37:45)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#3 2018-04-13 19:20:41

awesomepilot
Member
Registered: 2012-09-28
Posts: 18

Re: [SOLVED] Trying to use an f for loop, but its not working right.

OHhhhhhhhhh!   Yeah the ? wildcard will get just that last character instead of all the devices AND their partitions.  I was wondering about that, thanks for that!  The code you posted is a little confusing for me.  I'm still somewhat a beginner as you can see from my sloppy jolopy code.  So first we are passing the "find /dev/ -name 'sd?' to a loop that reads the results of find and passes it to $device?

Also what does $((++i)) mean?  Where is the i variable created, if that is a variable?  It works like a charm i'm just confused as to how it works.  Thanks so much!  I'm really excited, I love making headway in my scripting practice projects!

Last edited by awesomepilot (2018-04-13 19:21:41)

Offline

#4 2018-04-13 19:21:07

ayekat
Member
Registered: 2011-01-17
Posts: 1,250
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Trilby wrote:
find /dev/ -name 'sd?' | while read device; do
    printf '%d. %s\n' $((++i)) $device
    arrPics+=($device)
done

That won't work. Everything right of the pipe is executed in a subshell, so neither `device` nor `arrPics` will be available outside/after that while loop.

Why not simply like this?

for device in /dev/sd?; do
    # ...
done

--edit: Ah wait, if /dev/sd? does not match anything, this will cause the loop to be executed once with literally "/dev/sd?"... that may be a reason.

Last edited by ayekat (2018-04-13 19:24:03)

Offline

#5 2018-04-13 19:36:18

awesomepilot
Member
Registered: 2012-09-28
Posts: 18

Re: [SOLVED] Trying to use an f for loop, but its not working right.

I am unable to echo individual elements from the array, is that what you are talking about ayekat?

Last edited by awesomepilot (2018-04-13 19:36:52)

Offline

#6 2018-04-13 19:43:31

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

True, just move the find command to a process substitution subshell fed to stdin at the end of the loop though and it should work.

But the select option is really the best approach, I just figured I'd leave it to the OP to read up on that.  As for /dev/sd? not matching anything, that's one reason to favor 'find', though you could just set nullglob to avoid that too.  In any case, none of this reall matters if this is restricted to bash anyways:

#!/bin/bash

PS3='Enter the number of the device to format: '
select device in /dev/sd?; do
        printf 'Formatting %s\n' $device
        # do something horrible to $device here...
        break
done

"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#7 2018-04-13 19:47:01

awesomepilot
Member
Registered: 2012-09-28
Posts: 18

Re: [SOLVED] Trying to use an f for loop, but its not working right.

What do you mean, it doesn't matter if it is restricted to bash anyway?  This is script isn' t going to format the drives it is going to call a formatter like fdisk or parted to do the actual formatting.  This is part of an Archlinux install script i'm working on, so this is going into a larger project.

Offline

#8 2018-04-13 19:49:11

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

But you are calling bash, so the script can use bashisms like 'select' and 'nullglob'.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#9 2018-04-13 19:53:31

awesomepilot
Member
Registered: 2012-09-28
Posts: 18

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Okay I saw stuff about globs earlier in my reading before posting here.  I guess ill go study up on thos two things.  Thanks for pointing me in the right direction.  I'll mark this as solved since you pretty much solved the initial problem, i just need to learn some more things before I can do this. Thanks again!

Offline

#10 2018-04-13 22:00:46

Cody Learner
Banned
Registered: 2017-12-06
Posts: 54
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Trilby wrote:
#!/bin/bash

find /dev/ -name 'sd?' | while read device; do
    printf '%d. %s\n' $((++i)) $device
    arrPics+=($device)
done
# ... go on to get user's choice here
awesomepilot wrote:

what does $((++i)) mean?

I'm also curious about:

$((++i))

and the

'%d.

and

%s

in this:

printf '%d. %s\n'

Are these C language constructs?

I read the printf manpage "and all C format specifications". 
And: http://tldp.org/LDP/abs/html/dblparens.html

To come to the C construct conclusion. Other than learning C, is there info available?

Last edited by Cody Learner (2018-04-13 22:13:45)


Self designated Linux and Bash mechanic.....
I fix and build stuff hands on. I'm not opposed to creating a mess in obtaining a goal.

Offline

#11 2018-04-13 22:20:32

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#12 2018-04-13 22:37:26

Eschwartz
Trusted User/Bug Wrangler
Registered: 2014-08-08
Posts: 2,046

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Trilby wrote:

But you are calling bash, so the script can use bashisms like 'select' and 'nullglob'.

Lack of nullglob is hardly a restriction. POSIX has

for i in /dev/sd?; do
    if [ -b "$i"]; then
        do_something
    fi
done

Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#13 2018-04-13 22:43:33

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

I didn't say this couldn't be done in POSIX shell - that's all I'd use.  But the OP was already explicitly using BASH, in which case using nullglob for something like this is a nobrainer, and using `select` I guess is a half-brainer.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#14 2018-04-14 00:01:43

Cody Learner
Banned
Registered: 2017-12-06
Posts: 54
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Thanks, but TLDR the entire Gregs wiki.

I guess you didn't want to be helpful based on, read Greg's bash wiki reply? Not even a helpful hint, like pre-increment operator? Was able to find the terminology on Greg's wiki though. I often find it difficult to find info on a subject without the proper underlying terminology.

Short answers:

((++i)) is an arithmatic pre-increment operator. It adds one to the variable each time it is ran.

example:

i=1
((++i))
echo $i

What I found on the printf C format specs.

conversion character     argument type

d, i     An integer, expressed as a decimal number.
o     An integer, expressed as an unsigned octal number.
x, X     An integer, expressed as an unsigned hexadecimal number
u     An integer, expressed as an unsigned decimal number.
c     An integer, expressed as a character. The integer corresponds to the character's ASCII code.
s     A string.
f     A floating-point number, with a default precision of 6.
e, E     A floating-point number expressed in scientific notation, with a default precision of 6.
p     A memory address pointer.
%     No conversion; a literal percent sign ("%") is printed instead.

I've never found echo to not do what I needed so far. Your code would be an example of needing more than echo is capable.

Sorry if I'm being offensive in any way. Having a learning disorder and dyslexia sometimes causes me to misinturperate the intention in written communications. It also makes learning and remembering new things considerably more time consuming and difficult for me than for most others.

My title as mechanic, because I'm addmitedly very very far from possessing the abilities to ever be a computer scientist, software engineer, developer, etc, having an advanced degree in anything, or from being intellectually gifted as many here seem to be.


Self designated Linux and Bash mechanic.....
I fix and build stuff hands on. I'm not opposed to creating a mess in obtaining a goal.

Offline

#15 2018-04-14 00:26:01

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Cody Learner wrote:

Thanks, but TLDR the entire Gregs wiki.

If you want to understand the basics of shell scripting, you should read it ... the entire thing.  It's not long.

Cody Learner wrote:

I guess you didn't want to be helpful...

I do like helping by encouraging others to learn.  Specific questions or questions for clarification are well worth while.  But when you ask a series of several questions all on basic concepts covered in any introductory tutorial on shell scripting, there is really no reason for the answer to be elaborated here: you should be pointed to a basic tutorial to get started, which is what I gave you.

And look, it seems to have worked.  Gratitude is not needed, but don't get snarky when I pointed you in a direction that led you to learn, and potentially even to learn a little more than the answers to the specific questions you asked.

Last edited by Trilby (2018-04-14 00:27:48)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#16 2018-04-17 17:34:02

Cody Learner
Banned
Registered: 2017-12-06
Posts: 54
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Gratitude is not needed

Well deal with it, lol.  Trilby, you've played a large part in motivating me to expand my understanding of bash scripting. Thank you for that.

On the other hand, I'm also well aware of my limitations, and try to manage my hobby of Linux and shell scripting by not pushing it to the point that it becomes unpleasant. I could only wish for the ability to be able to read a wiki and retain enough of it to be able to implement even a small percentage of what I just read. Comprehension and retention of written information is very much a variable across the population. I believe that most people falling within the lower third of this curve tent to not willingly partake in activities involving it. The ones falling within the top third likely gravitate towards activities that do require it (like scripting, programming, etc ) with some of them ending up here as the experts.

Unfortunately, I fall solidly withing the lower third. If time spent researching and reading material related to Linux and shell scripting correlated directly to abilities, having around 10 (casual) years of Linux usage with 8-9 years Arch, and probably around 6 months to a year (on and off) of shell scripting, I should be a f-ing whizz by now! However, that's obviously not the case, but I still enjoy it.

I'm very persistent, focus on learning one new concept at a time, usually because it's required in something I'm doing. I believe I've just recently gotten to the point of understanding the terminology enough, that reading about shell scripting concepts are beginning to "add up" and are making some sense, rather than seeming like reading an unknown foreign language.

After your suggestion of reading Gregs wiki, I've downloaded and have been reading 'Advanced Bash-Scripting Guide' by Mendel Cooper, 10 Mar 2014 edition. I find Greg's a good source of quick info, but reading and navigating it as a whole, I find difficult compared to a book format. Hopefully I stay with it and get something worthwhile out of it.

Please try to keep some of this in mind if / when you may see someone as being lazy or whatever. I saw the op ask a question about '$((++i))', that went unanswered. I was also curious as to what it was doing. It lead me to a bit of searching, and then expanded to some things in the printf command I couldn't find in the man page. This lead to the C language question. These very well may fall into the category of being so basic, they are covered an any basic bash guide. However, it was not obvious to me. Searching for this,  '$((++i))'  because I didn't know the terminology didn't seem productive is part of why I asked. Unlike your usual helpful comments and replies, the link to Greg's was honestly not much help in this particular case. I also found it somewhat annoying, as per my snarky reply.

Don't get burned out by helping us out though! You're a valuable source of knowledge with an exceptional amount of patience. Hopefully you'll continue to share those assets with the community.

Last edited by Cody Learner (2018-04-17 20:34:24)


Self designated Linux and Bash mechanic.....
I fix and build stuff hands on. I'm not opposed to creating a mess in obtaining a goal.

Offline

#17 2018-04-18 10:01:10

ayekat
Member
Registered: 2011-01-17
Posts: 1,250
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Cody Learner wrote:

Please try to keep some of this in mind if / when you may see someone as being lazy or whatever. I saw the op ask a question about '$((++i))', that went unanswered. I was also curious as to what it was doing. It lead me to a bit of searching, and then expanded to some things in the printf command I couldn't find in the man page. This lead to the C language question. These very well may fall into the category of being so basic, they are covered an any basic bash guide. However, it was not obvious to me. Searching for this,  '$((++i))'  because I didn't know the terminology didn't seem productive is part of why I asked. Unlike your usual helpful comments and replies, the link to Greg's was honestly not much help in this particular case. I also found it somewhat annoying, as per my snarky reply.

We do acknowlege that not everyone knows everything about scripting/programming, but that is not an excuse not to go and read the provided resources, especially if you asked for them (posts 10/11).

And for the given link, if you have no idea how shell scripting works, you will likely want to start with this page in the given guide. You would learn that $ has a special meaning, and that $((...)) has got something to do with "arithmetic expressions", so now you know that you may want to consult this page.

Then, knowing a little programming (or searching the Web a bit, as you have), you will learn that ++i generally means "increment i (by 1) and yield the new value" (there is also i++, which is slightly different and more headache-inducing to newcomers—search the web for "pre-increment" and "post-increment" to get an idea).

If you put two and two together, you may conclude that $((++i)) means: "Increment the value of i and yield that".

But what is i defined as initially? It turns out that bash will interpret an undefined value as 0 in the context of arithmetic expressions, so the first invocation will yield "1". This part could have been deduced by just trying it out.

... and this is a general recommendation to about all things related to programming: Try things out. You don't learn programming by just looking at books, guides and theories. smile

Last edited by ayekat (2018-04-18 11:39:08)

Offline

#18 2018-04-18 11:28:59

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 19,542
Website

Re: [SOLVED] Trying to use an f for loop, but its not working right.

Cody Learner wrote:

Trilby, you've played a large part in motivating me to expand my understanding of bash scripting. Thank you for that.

Your welcome.  I've commented on these forums before that your approach is generally right on track and I suspect you have good potential to learn scripting and/or programming.  But with that comes a form of respect in believing that you are capable of doing a bit of your own leg work and being told - effectively - to RTFM when that's the warranted response.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

Board footer

Powered by FluxBB