user2268507
user2268507

Reputation:

Cut unix variable

I have the following at the moment:

for file in *
  do
  list="$list""$file "`cat $file | wc -l | sort -k1`$'\n'
  done

echo "$list"

This is printing:

fileA 10
fileB 20
fileC 30

I would then like to cycle through $list and cut column 2 and perform calculations.

When I do:

for line in "$list"
  do
     noOfLinesInFile=`echo "$line" | cut -d\  -f2`
     echo "$noOfLinesInFile"
  done

It prints:

10
20
30

BUT, the for loop is only being entered once. In this example, it should be entering the loop 3 times.

Can someone please tell me what I should do here to achieve this?

Upvotes: 0

Views: 230

Answers (4)

glenn jackman
glenn jackman

Reputation: 246774

wc -l will only output one value, so you don't need to sort it:

for file in *; do
    list+="$file "$( wc -l < "$file" )$'\n'
done
echo "$list"

Then, you can use a while loop to read the list line-by-line:

while read file nlines; do
    echo $nlines
done <<< "$list"

That while loop is fragile if any filename has spaces. This is a bit more robust:

while read -a words; do
    echo ${words[-1]}
done <<< "$list"

Upvotes: 0

konsolebox
konsolebox

Reputation: 75478

Use arrays instead:

#!/bin/bash

files=()
linecounts=()

for file in *; do
    files+=("$file")
    linecounts+=("$(wc -l < "$file")")
done

for i in "${!files[@]}" ;do
    echo "${linecounts[i]}"
    printf '%s %s\n' "${files[i]}" "${linecounts[i]}"  ## Another form.
done

Although it can be done simpler as printf '%s\n' "${linecounts[@]}".

Upvotes: 0

choroba
choroba

Reputation: 241828

If you quote the variable

for line in "$list"

there is only one word, so the loop is executed just once.

Without quotes, $line would be populated with any word found in the $list, which is not what you want, either, as it would process the values one by one, not lines.

You can set the $IFS variable to newline to split $list on newlines:

IFS=$'\n'
for line in $list ; do
   ...
done

Don't forget to reset IFS to the original value - either put the whole part into a subshell (if no variables should survive the loop)

(
  IFS=$'\n'
  for ...
)

or backup the value:

IFS_=$IFS
IFS=$'\n'
for ...
    IFS=$IFS_
    ...
done

Upvotes: 1

user3929561
user3929561

Reputation: 41

This is because list in shell are just defined using space as a separator.

# list="a b c"
# for i in $list; do echo $i; done
a
b
c
# for i in "$list"; do echo $i; done
a b c

in your first loop, you actually are not building a list in shell sens. You should setting other than default separators either for the loop, in the append, or in the cut...

Upvotes: 0

Related Questions