33

Sometimes I have a one-liner that I am repeating many times for a particular task, but will likely never use again in the exact same form. It includes a file name that I am pasting in from a directory listing. Somewhere in between and creating a bash script I thought maybe I could just create a one-liner function at the command line like:

numresults(){ ls "$1"/RealignerTargetCreator | wc -l }

I've tried a few things like using eval, using numresults=function..., but haven't stumbled on the right syntax, and haven't found anything on the web so far. (Everything coming up is just tutorials on bash functions).

2
  • tell me the number of files in the directory $1/RealignerTargetCreator. Commented Feb 17, 2016 at 19:38
  • 3
    you re missing the semicolon at the end. ... ; } Commented Mar 29, 2018 at 12:09

5 Answers 5

43

Quoting my answer for a similar question on Ask Ubuntu:

Functions in bash are essentially named compound commands (or code blocks). From man bash:

Compound Commands
   A compound command is one of the following:
   ...
   { list; }
          list  is simply executed in the current shell environment.  list
          must be terminated with a newline or semicolon.  This  is  known
          as  a  group  command. 

...
Shell Function Definitions
   A shell function is an object that is called like a simple command  and
   executes  a  compound  command with a new set of positional parameters.
   ... [C]ommand is usually a list of commands between { and },  but
   may  be  any command listed under Compound Commands above.

There's no reason given, it's just the syntax.

Try with a semicolon after wc -l:

numresults(){ ls "$1"/RealignerTargetCreator | wc -l; }
Sign up to request clarification or add additional context in comments.

7 Comments

Well, that was simple! (I mean the semicolon). Again, its always good to get a deeper understanding of how the shell works.
The semicolon is necessary because } is not a control character and does not terminate a command. Notice echo } simply outputs the literal string.
@chepner That's just pushing the question one level down. Those who created the grammar could make } special for functions. zsh, for example, has no problems with foo () {echo foo}.
I'm describing what is, not what could be.
@chepner And I'm saying it isn't necessary, it's just the way the syntax is.
|
4

Don't use ls | wc -l as it may give you wrong results if file names have newlines in it. You can use this function instead:

numresults() { find "$1" -mindepth 1 -printf '.' | wc -c; }

3 Comments

Thanks. It's always good to deepen one's bash skills! Just curious, how could a file name have a newline in it?
You can use touch $'file\nwith\nline' to create a filename with newlines
@abalter Yep. That's why it's a mantra: Don't parse ls output.
4

You can get a

bash: syntax error near unexpected token `('

error if you already have an alias with the same name as the function you're trying to define.

Comments

3

You can also count files without find. Using arrays,

numresults () { local files=( "$1"/* ); echo "${#files[@]}"; }

or using positional parameters

numresults () { set -- "$1"/*; echo "$#"; }

To match hidden files as well,

numresults () { local files=( "$1"/* "$1"/.* ); echo $(("${#files[@]}" - 2)); }
numresults () { set -- "$1"/* "$1"/.*; echo $(("$#" - 2)); }

(Subtracting 2 from the result compensates for . and ...)

2 Comments

The first of the hidden files functions could use dotglob, since it's using arrays anyway.
Hm, for some reason I remembered dotglob matching . and .. as well, but it doesn't.
-3

The easiest way maybe is echoing what you want to get back.

function myfunc()
{
    local  myresult='some value'
    echo "$myresult"
}

result=$(myfunc)   # or result=`myfunc`
echo $result

Anyway here you can find a good how-to for more advanced purposes

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.