Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Someone care to enlighten me as to why the spaces in the first command seem to be interpreted as line breaks? Also occurs substituting print for echo.

$for l in $( find *.txt -exec head -1 {} \; ); echo $l;
9.16.11
09:20
9.19.11
18.41
9.21.11
07:15
$find *.txt -exec head -1 {} \;
9.16.11                 09:20
9.19.11                 18.41
9.21.11                 07:15
share|improve this question
2  
See Don't read lines with for –  jw013 Oct 8 '11 at 20:21
add comment

2 Answers 2

up vote 2 down vote accepted

Check out the man page for your shell looking specifically at the IFS global variable.

Specifically, do this:

IFS=$(echo -en "\t\n\0")

share|improve this answer
    
echo $IFS | hexdump -c Has revealed $IFS to contain "\t \n \0 \n" But I'm still confused as to what I have to to keep the spaces from being interpreted as new lines? –  CuriosityCasualty Oct 8 '11 at 20:17
    
try hexdump -C there are actually 5 characters -c is displaying, the first is ' ' –  frogstarr78 Oct 8 '11 at 20:20
1  
In short, the space character is included in the IFS variable. To prevent that reset IFS: IFS=$(echo -en "\t\n\0") –  frogstarr78 Oct 8 '11 at 20:21
    
That did it! Thanks you. –  CuriosityCasualty Oct 8 '11 at 20:44
2  
@frogstarr78 - There's no need to use echo for that, in bash, just use $'\t\n\0'. –  Chris Down Oct 8 '11 at 20:53
show 1 more comment

Your command substitution induces word splitting on its output, based on IFS. Specifically, in this case it is splitting on spaces. Do not parse the output of find. Instead, do this:

for file in *.txt; do
    head -1 "${file}"
done

If you truly wanted to read by line, you'd use read instead of for (but you don't want to do that in this instance), like the following example in bash:

while IFS= read -r file; do
    head -1 "${file}"
done < <(find *.txt)

This would still break, for example, on a newline in the file name. Use a glob, it is much safer.

The Wooledge wiki also has some good information on this issue here.

share|improve this answer
    
This won't break: set -f; find . -name '*.txt' -print0 | while IFS= read -r -d $'\0' file; do head -1 "$file" ;done . . . The set -f disables pathname expansion –  Peter.O Oct 9 '11 at 15:58
    
@fered An inferior method, nonetheless. –  Chris Down Oct 11 '11 at 21:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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