I'm using csh for a project (forced into it, sorry), and one component of my script uses variations of the following in a large block of its functionality:

find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID

This works as intended in my script, but I need to have this set into a variable so that I can change my expression and grep results (have a large switch statement which modifies this string). I've tried a number of things, but I can't seem to get it to work. So not only am I using CSH, I'm also loading commands into variables (also I no no, again, sorry), but for this very specific case I'd like to try to make this work, if possible. I feel like it's a quoting/formatting issue only, otherwise I would abandon this entirely.

Here's what I've done:

Double quotes:

set findString = "find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID"

This echo's back fine, but when find is executed, I get the following error:

find: paths must precede expression: |

I realize that the shell will try to expand it before executing the command, but I'm not sure exactly how to get past this (I can't seem to quote it so that it works right). I've tried putting it in quotes the following ways:

set findString = "find . -maxdepth 1 -not -type d \"|\" awk '{gsub(/.\//,"")}1' | grep $userID"
set findString = "find . -maxdepth 1 -not -type d \"| awk '{gsub(/.\//,"")}1' | grep $userID\""
set findString = "find \". -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID\""
set findString = "\"find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1 | grep $userID'\""

And received the following on each:

Unmatched ".

Then I tried single quotes, but cannot seem to get this to even echo back:

set findString = 'find . -maxdepth 1 -not -type d | awk \'{gsub(/.\//,"")}1\' | grep $userID'
echo $findString

Again: Unmatched '.

At this point, I again tried using the double quotes but escaped all of the csh Meta characters:

set findString = "find\ .\ \-maxdepth\ 1\ \-not\ \-type\ d\ \|\ awk\ \'\{gsub(/.\\//,\"\"\)}1\'\ \|\ grep\ \$userID"

Nope. So I found another thread that referenced this helpful document on quoting, and tried to implement it differently. I ended up taking find out of the variable and just loading the rest of the string in the variable as search options. I also peeled off the grep pipe to try to zero in on this. It looked like:

set findString = ( \( -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' \) )
echo $findString
find . "${findString}"

And though find runs, it doesn't evaluate properly. I feel like there surely must be a way to do this.

I'm stuck. I would appreciate any assistance on this, and again apologize for committing a double atrocity with CSH and loading this command string to a var.


1 Answer 1


I don't think you can put a | in a variable and have it interpreted as starting a pipeline after the variable is expanded without eval.

So, what you could do, would be to put the find arguments to one variable, and the awk command to another:

This seems to work for me (on tcsh):

> mkdir dir; touch dir/file
> set findopts = '-type f'
> set awkcmd = '{gsub(/.\//,"")}1'
> find . $findopts | awk "$awkcmd" 

Though, ./ matches any character followed by a slash, so maybe you wanted to escape the dot too:

> set awkcmd = '{gsub(/\.\//,"")}1'
> find . $findopts | awk "$awkcmd"

Or with eval, if you insist:

> set cmd = 'find . -type f | awk '\''{gsub(/\.\//,"" ) }1'\'
> eval "$cmd"

Frankly, I don't know about the quoting subtleties of csh (and have no interest in finding out). The above seems to work similarly to POSIX-like shells, but do check for yourself.

  • This makes perfect sense, and worked like a charm. I used the first of the options you mentioned. Many thanks!
    – enegence
    Commented Feb 12, 2018 at 6:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .