I have wrote following meta-project file for qmake that is designed to build all .pro files in the following subdirectories (for historical reasons and because of other toolchains, the file names do not match folder names). Which essentially boils down to something like this (throwing aside project-specific stuff)THIS_FILE=make-all.proTEMPLATE=subdirsFIND= find -name \'*.pro\' -printf \'%p\\n\'AWK= awk \'{$1=substr($1,3); print}\'RMTHIS= awk \'!/$$THIS_FILE/\'SUBDIRS= $$system($$FIND | $$AWK | $$RMTHIS )I need to get a list of folders that contain .pro files within a Bash script, so I decided to copy the method #!/bin/bashFIND=find -name '*.pro' -printf '%h\\nAWK=awk '{\$1=substr(\$1,3);printf}'SUBDIRS=$($FIND | $AWK)Apparently this doesn't work, awk was spewing error invalid char '' in the expression. Trying to execute same lines in Bash directly had shown that awk actually works only if double quotes are used find -name '*.pro' | awk {\$1=substr(\$1,3);printf}Replacing the line in question withAWK='awk {$1=substr($1,3);printf} 'gave no working result, the output of script is empty, unlike the output of manually entered command. Apparently find -name '*.pro' In script finds only files in current folder, while its counterpart in command line of bash find it in subfolders. What is wrong and why qmake works differently as well?
Escaping double quotes for variables in bash and qmake
bash;find;escape characters
I'm not familiar with qmake syntax, but from your sample it uses quotes and variables in very different ways than shells. So you can't just use the same code.http://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters covers what you need to know, so here I'll just summarize what's relevant for your question.In a nutshell, you cannot simply stuff a shell command into a string. Shells such as bash do not parse strings recursively. They parse the source code and build commands as lists of strings: a simple command consists of a command name (path to an executable, function name, etc.) and its arguments.When you use an assignment like AWK=awk '{\$1=substr(\$1,3);printf}', this sets the variable AWK to a string; when you use the variable as $AWK outside double quotes, this turns the value of the variable into a list of strings by parsing it at whitespace but it does not parse it as shell code, so characters like ' end up being literally in the argument. This is rarely desirable, which is why the general advice on using variables in the shell is to put double quotes around variable expansions unless you know that you need to leave them off and you understand what this entails. (Note that my answer here does not tell the whole story.)In bash, you can stuff a simple command into an array.#!/bin/bashFIND=(find -name '*.pro' -printf '%h\\n')AWK=(awk '{$1=substr($1,3);print}')SUBDIRS=$(${FIND[@]} | ${AWK[@]}) But usually the best way to store a command is to define a function. This is not limited to a simple command: this way you can have redirections, variable assignments, conditionals, etc.#!/bin/bashfind_pro_files () {  find -name '*.pro' -printf '%h\\n'}truncate_names () {  awk '{$1=substr($1,3);print}'}SUBDIRS=$(find_pro_files | truncate_names)I'm not sure what you're trying to do with this script (especially given that you change the find and awk code between code snippets), but there's probably a better way to do it. You can loop over *.pro files in subdirectories of the current directory withfor pro in */*.pro; do  subdir=${pro%/*}  basename=${pro##*/}  doneIf you want to traverse subdirectories recursively, in bash, you can use **/*.pro instead of */*.pro, but beware that this also recurses into symbolic links to directories.