LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   "for and while looping" questions (https://www.linuxquestions.org/questions/linux-newbie-8/for-and-while-looping-questions-4175412550/)

iconig 06-20-2012 05:22 PM

"for and while looping" questions
 
I have been trying to come up with a program that can do this:
Say I have a file named "sire" with a single field;
10
229
288
35
83
47
3
I want to create a file "gen" with three fields with the data in file "sire" listed in field 1 while field 2 and 3 are just 1 each like this:
10 1 1
229 1 1
288 1 1
etc
I want to use this to solve an equation of the form "itgen -m 500 -r gen b beta -n inverseNRM
-m 500 indicates the number of rounds to iterate
-r gen is the right hand side of the equation
-b beta is the filename for the solution
-n inverseNRM is another file with three fields.

Really need help here. Thanks

Tinkster 06-20-2012 05:27 PM

sed 's/$/ 1 1/' sire > gen

... and it's NOT urgent to any of us; please don't be rude,
we're all volunteers here, donating our precious spare time.

iconig 06-20-2012 05:34 PM

I never intended to be rude. I was told the title of my first post was inappropriate and I was to use something like urgent and name of program which I just did.
Its important to me, sorry if I offended you

Tinkster 06-20-2012 08:09 PM

Interesting .. who told you that?

:)

That aside - did the sed command do the trick for you?



Cheers,
Tink

iconig 06-25-2012 01:04 PM

the sed gave me a file with three fields which is a step. I am actually trying to run a while loop such that it reads every line and it uses each line to do a command ("itgen -m 500 -r gen b beta -n inverseNRM) which I saved in a file called perm. It should output each result for each line after doing the command. I tried using something like this:

IFS=$'\n';for line in `cat gen`; do ./perm ${line} > ${line}; done.

When I did this, it said permission denied, although it gave me each line of gen, there was no content.
I am a little new in programing, I will appreciate some help thank you

grail 06-25-2012 03:44 PM

So you wrote that line at the command prompt or this is inside yet another file?

Also, is the perm file executable and have the interpreter (maybe bash) set at the top?

I think you need to fill in some more blanks before we can assist.

Tinkster 06-25-2012 03:46 PM

I must say I don't quite understand how the initial request and the
itgen -m 500 -r gen b beta -n inverseNRM
hang together ... irrespective of the content of the line you wish
to run the same command over and over?
\
How does the BOLD bit above hang together w/ ./perm?


Can you give us a fleshed out example of input, and the desired
effect, plus the expected output?

iconig 06-25-2012 04:45 PM

I used IFS=$'\n';for line in `cat gen`; do ./perm ${line} > ${line}; done on the command prompt. I saved itgen -m 500 -r gen b beta -n inverseNRM in a file called perm. The content of perm is an equation I want to solve. Its like gen X beta= inverseNRM, then beta= gen-1 X inverseNRM. But that is a different program on my computer. inverseNRM is another file

iconig 07-11-2012 11:47 AM

how to read each file in a directory and pass each file separately into a do command
 
Code:

I have been trying to read files in a directory then pass it to a command so that each file gets processed in the do command and the output after the command gets stored separately file by file.
I have this directory:
Code:

home/pro/connection
The files in the directory connection are names:
S1:
Code:

21 3 2
S2
Code:

20 1 2
Code:

I want to loop through each file and send each file to be processed in the do command, then the result of each file processed gets saved differently and each gets moved into one folder.
Something like this:

Code:

#!/bin/bash
i=1
FILES=/home/pro/connection/*
for f in $FILES
do
eacho "Processing of $f file...:# take action on each file. $f store current file name
cat $f | command # output from this command for S1 is beta >> beta >> beta.$i # so file S1 and S2 have outputs beta1 and beta2
done

Code:

can I use while command for this as well?
Code:

Is it possible to create S1 and S2 without having to output them just create them and send them separately to the do command? The final output (beta1 and beta2) are more important than outputting files S1 and S2 (though I need them to get sent to the do command)
Thanks

Farzan Mufti 07-11-2012 12:11 PM

Linux, Bash Script
 
You can certainly use while, however, for .. do .. done is, IMHO, a better approach. So your code should look something like

#/bin/bash
DIRECTORY=/home/pro/connection
OUTPUT_FILE=$DIRECTORY/out.txt
#Please choose a command
#COMMAND=something
COMMAND='ls -l'
for f in $DIRECTORY/*
do
echo "Processing file $f"
#Applying this command onto each file separately
#And redirecting (appending) to an output file
$COMMAND $f >> $OUTPUT_FILE
done

If you want to create files without redirection, you can simply use the touch command
touch afile bfile

For details of this command you can check the man pages
man touch


Kindly elaborate if you have any more questions and I would be glad to assist.

Regards,
Farzan Mufti

David the H. 07-11-2012 12:50 PM

Please use ***[code][/code] tags*** around your code and data, to preserve formatting and to improve readability. Please do not use quote tags, bolding, colors, or other fancy formatting.

And iconig, please use them only for code and data. Don't put them around the explanation text. I can hardly read your post.

Code:

for f in $(ls $DIRECTORY)
No, no no. Don't read lines with for, and don't parse ls! Use simple globbing instead:

Code:

for f in $DIRECTORY/*; do
Code:

COMMAND='ls -l'
Again, no, no, no. Variables are for storing data, not code. Use a function.

I'm trying to put a command in a variable, but the complex cases always fail!
http://mywiki.wooledge.org/BashFAQ/050


This is incorrect too:
Code:

FILES=/home/pro/connection/*
Don't use a single variable for storing lists of things, like files. If you don't want to loop over them directly, as above, use an array.


Here are a few useful bash scripting references:
http://mywiki.wooledge.org/BashGuide
http://mywiki.wooledge.org/BashFAQ
http://mywiki.wooledge.org/BashPitfalls
http://wiki.bash-hackers.org/scripting/newbie_traps
http://www.linuxcommand.org/index.php
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/index.html
http://www.gnu.org/software/bash/manual/bashref.html
http://wiki.bash-hackers.org/start
http://ss64.com/bash/

Start with the first one, the BashGuide. It will explain all the basic features of bash scripting.

Farzan Mufti 07-12-2012 05:58 AM

Bash scripting
 
Well,
In advanced shell scripting variables ARE used to store commands also. It makes the code a lot more readable.

There is simply nothing wrong with
Code:

FILES=/home/pro/connection/*
It is very common in Bash scripting to do this and has no problem with it. There is no "no no" to it, period. It is not wrong because first, it runs in Bash and second, it is not a bad practice. Bash for statement works fine with it and making it an array is needless.

for f in $DIRECTORY/*

would be good.
If you want to get file list of the current directory, you can do like
Code:

for f in *
do


David the H. 07-12-2012 11:16 AM

I completely disagree with you, and so do all the very smart people at the wooledge site and others. You should always use the right tool for the right job.

Contrary to your assertion, putting the command in a variable obscures what's being run. It blurs the line between data and code. Not to mention that the shell parsing rules make it tricky-to-impossible to handle special characters like spaces inside them. Again, variables are for data (or at most arguments to commands), and functions are for code.

As for arrays, a scalar variable holds a single value, and you'd have to rely on shell word-splitting or other unreliable splitting techniques to extract multiple entries from them. But arrays are specifically designed for storing and operating on multiple entries of related values. They are particularly suited for working with lists of filenames, in cases where you can't just loop over them directly.

Actually, I do have to apologize in regards to my initial criticism. globs don't expand in "var=value" lines, so actually this is acceptable:
Code:

FILES=/home/pro/connection/*
for f in $FILES

"$FILES" expands into the globbing pattern, and the pattern then expands into a list of files that the for loop can safely accept. The variable never actually contains the file list itself.

But as for "for f in $(ls directory)", I say it again, and even louder...NO, NO, NO, NO, NO! The for loop is simply not designed for processing the output from commands like ls or cat. Read the link I gave carefully and please do not ever suggest it again. I'm serious. The only time it is acceptable is when you use a command that outputs discreet values that are not affected by word-splitting and globbing expansion, such as seq.

iconig 07-12-2012 02:37 PM

well either of your suggestion is not doing what I need, I would like each file to be processed by the program
Code:

itgen -m 500 -r rhs -b beta -n inv
The each file is supposed to be opened and read as rhs, then the output file from each line with this command is beta, so I will have
Code:

beta.1, beta.2 etc

Tinkster 07-12-2012 03:15 PM

I took the liberty to merge your two very closely related threads, and would
ask that you stick with one thread per topic in the future.


Cheers,
Tink


All times are GMT -5. The time now is 07:20 AM.