3

In Ubuntu desktop 20.04, I have 20 directories, each containing a text file with the same name, "weights". These text files contain ~20-30 numbers separated with a space. In each of the 20 directories, there is also a text file named "coefficient", which contains a single number.

I want to execute a shell command that goes into each directory, sums together all the numbers in the "weights" text file, and multiplies that sum by the number in the "coefficient" text file. If there was some way for this to be put into a csv that would be ideal, but even if it just prints to the terminal that would be okay too!

1
  • 1
    Thanks, I have now added this! – BennyD May 11 '20 at 21:48
2

Perl to the rescue!

perl -wle '
    for my $dir (@ARGV) {
        my $s = 0;
        open my $w, "<", "$dir/weights" or die "$dir: $!";
        $s += $_ for split " ", <$w>;
        open my $c, "<", "$dir/coefficient" or die "$dir: $!";
        print $s * <$c>;
}' -- */
  • -w turns on warnings
  • -l removes newlines from input and adds them to output
  • the argument */ is expanded by the shell to all the directory names in the current directory (you can specify path/to/parent/directory/*, too)
  • open opens a file, "<" means for reading, $w and $c are the corresponding file handles
  • the diamond operator <$w> reads a line from the given file handle
3
  • Brilliant! Thank you thank you thank you! – BennyD May 12 '20 at 3:15
  • As a followup, is there a way to then compile each of these into a single csv? – BennyD May 12 '20 at 4:28
  • Just append | sed '$!a,' | tr -d '\n'. – choroba May 12 '20 at 9:52
0

bash, coreutils and bc

You can generate the arithmetic expression with the standard programs like this:

for dir in *; do 
  printf "("
  tr ' ' + < $dir/weights | tr -d '\n'
  printf ") * "
  printf "%s\n" $(<$dir/coefficient)
done | bc -l

Note this assumes you do not have extraneous white space in your files.

Demo

Generate sample data

mkdir -p testdir/{a..z}
cd testdir
for dir in *; do 
  n=$(shuf -r -i 20-30 -n1)
  shuf -r -i 0-100 -n $n | paste -d' ' -s > $dir/weights
  seq 0 .01 1 | shuf -n1 > $dir/coefficient
done

Output when script is run in testdir/

1214.19
970.97
776.03
449.48
803.76
696.01
514.71
789.36
169.44
615.50
972.48
688.50
1290.76
635.97
824.90
787.39
83.36
1048.32
956.25
203.36
1144.66
327.70
65.40
367.68
828.80
919.75

Append | paste -d, -s to bc if you want the output to be comma-separated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.