I've run into a something that I don't understand, and I've managed to reproduce the situtation in the script below.

If I source the script it fails with head: 1: invalid number of lines. But if the script is executed as a script it succeeds.

# !/bin/bash
# test.sh
function getline { 
    local line=$(cat /etc/passwd  | cut -d':' -f1 | grep --no-messages -nw "$1" | cut -d':' -f1) 
    /usr/bin/head -n $line /etc/passwd | tail -n 1  

# Call the function
getline root

Debug output if sourced and then called (set -x)

+ getline root
++ cat /etc/passwd
++ cut -d: -f1
++ cut -d: -f1
++ grep --colour=always -niw root
+ local 'line=1'
+ tail -n 1
+ /usr/bin/head -n '1' /etc/passwd
/usr/bin/head: 1: invalid number of lines

Debug output if executed directly:

+ /tmp/test.sh
++ getline root
+++ cat /etc/passwd
+++ cut -d: -f1
+++ cut -d: -f1
+++ grep -niw root
++ local line=1
++ /usr/bin/head -n 1 /etc/passwd
++ tail -n 1

So it seems the $line assignment argument gets quoted in the first case, + local 'line=1' vs ++ local line=1, which seems to lead to different results, why is that? Also if the line variable is not local the quotations move to the variable: ++ line='1'

These results come from GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu).


Explicitly use /usr/bin/head => same results.

  • Make sure that head is really something like /usr/bin/head, not an alias or a function from bash_it or something like that. otherwise it is treated wrong way if sourcing and is not if executed in a subshell. – theoden Jul 27 '15 at 9:46
  • Works properly at my bash and zsh. – theoden Jul 27 '15 at 9:52
  • @theoden: Which bash version? Could you source the script with set -x to compare output? Sourcing in zsh also works for me. – mandrake Jul 27 '15 at 9:55
  • sure – theoden Jul 27 '15 at 10:03

There was an alias for grep to always color which screwed things up and probably left some escape sequence that didn't show up with set -x.

So the solution to this particular problem is to either execute grep explicitly without colors ... | grep --color=never, bypassing the alias using \ ... | \grep ....

Thanks to theoden which led me in right direction.

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.