Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to store commands in a file, so I can just easily call the file usnig the below bit of code;


I need to run this bit of code;

Set n=0 ; foreach sql ( *_*.sql)
foreach? sed “s/_/-/g” $sql
foreach? @ n ++
foreach? End
echo You changed $n files

I type the following;

set n = 0 > test
foreach sql ( *_*.sql) >> test

When I get to this point, I ave a blank line appear within the terminal so I type the following 3 lines blind;

foreach? sed “s/_/-/g” $sql
foreach? @ n ++
foreach? End

I then finish with:

echo 'echo You changed $n files' >> test

Once I finish the output file only contains this:

foreach? sed "s/_/-/g" $sql
foreach? @ n ++
foreach? end
echo You changed $n file

Totally missing out the set commands and the beginning of the foreach loop. What am I missing here? or is it just not possible?


set n=0
foreach sql ( *_*.sql )
sed "s/_/-/g" $sql
@ n ++
echo You changed $n files
chmod 777 test
share|improve this question
Is there a reason you're not just using a text editor? – Michael Mrozek Mar 5 '12 at 23:03
I initially tried that but weren't sure if it was best to do it this way. I've put the error i've been receiving while doing it within the answer comments below. – r0bb077 Mar 6 '12 at 9:44
up vote 3 down vote accepted

You still have multiple problems in your script.

First off, a text editor is the right way to create a script 99% of the time. Building it manually line by line with echo commands is tedious and offers no advantage at all. (The other 1% covers cases where you're on a system that doesn't have an editor you're familiar with, or where there's a good reason to use a program to generate a script automatically, neither of which should apply in your case.)

The first line should be #!/bin/tcsh -f, not #!/bin/tcsh. The -f tells it not to source your startup files (.tcshrc, .cshrc, .login), so your script will be self-contained. The lack of -f probably won't cause any problems, but having it is good practice. (Note: this does not apply to sh or bash scripts; for those shells, -f means something else entirely.)

This line:

sed "s/_/-/g" $sql

reads each file, changing all underscores to hyphens -- but the output is written to stdout, not back to the input file. The files themselves are not changed. Since you later do this:

echo You changed $n files

I presume that doesn't fit in with your plans.

Modifying files in place is actually moderately tricky. I'd do something like this:

sed "s/_/-/g" $sql > $sql.tmp && mv $sql.tmp $sql

This modifies the file $sql, writing the modified version to a temporary file. If that succeeds, it then renames the temporary file to $sql.

There's also a -i option to sed that will do something similar; another approach is:

sed -i.bak "s/_/-/g" $sql

Indentation is your friend. Everything between the foreach and end lines should be indented to show the structure of your code. (I use 4 spaces myself; some people prefer a different number of spaces, or use tabs.)

Finally, the chmod 777 test should not be in the test script itself. You need to execute that command from the command line, to make the test script executable. And 777 is a bad idea; it makes your script readable, executable, and writable by everyone on the system. Use chmod +x test instead.

Be sure you execute the script by typing ./test, not just test. (Your question says you're already doing that.) Otherwise, you might execute the built-in test command rather than your script. There's nothing wrong with naming your script test, as long as you (a) consistently use the ./test syntax to invoke it, and (b) you don't have the . directory in your $PATH.

If you're going to be writing a lot of scripts, you should consider using sh or bash rather than csh or tcsh. This essay explains why.

Finally (and this might be the most important lesson here), you haven't actually told us what you're trying to do. I think you want to modify the contents of certain files, replacing underscores with hyphens. Or do you want to change their names rather than their contents? It's impossible to be sure what you're trying to do, because all you've shown us is a chunk of code that doesn't work. There's nothing wrong with showing us non-working code, but we can't advise you how to fix it unless you tell us, in English, what you're trying to accomplish.

share|improve this answer
Hey Keith, I appreciate the detailed post but it just doesn't want to work. I'm now getting a message saying 'unknown option: `- Usage:tcsh [ -bcdefilmnnqstvVxX ] [ argument ... ]. I've been set a task where I need to change all types of a certain file that have an underscore character within them and record how many files I've actually changed. It's basically that simple, I just can't find any resources to help me figure out how it should actually be done. – r0bb077 Mar 7 '12 at 10:29
Ignore that it might of been what you originally said about the 'test' file name, I changed it to another random name and it worked fine. thanks for you help here! – r0bb077 Mar 7 '12 at 10:39
@r0bb077: I'm glad you got it working, but if you were invoking the script as ./test, the name of the script should not have made any difference. It must have been some other change that fixed the problem. – Keith Thompson Mar 7 '12 at 19:19

Trying what you're doing from the shell command line is fraught with problems. You have to echo and redirect every line and you have to quote any shell metacharacters lest they be interpreted by the current shell and not make it into the file you're creating. You are better off using a text editor to edit your test file and entering the shell commands directly there.

share|improve this answer
I had been trying this but I can't get the terminal to recognise the foreach loop. I have this within the file - 'foreach sql (_.sql)' but I keep getting error systax error at lie 2: `(' unexpected. Any ideas – r0bb077 Mar 6 '12 at 9:32
You're writing a tcsh-style script. Could it be that you're inadvertently trying to execute it with a Bourne type shell, e.g. bash or sh? That would explain the error message. Put #!/bin/tcsh at the top of the file to tell the system to use tcsh as the interpreter. – Kyle Jones Mar 6 '12 at 19:35
Hey Kyle, I appreciated your help here, but I'm getting error 'command not found' now i've inserted that. I've edited my original post above to show you what i've got in my file now. Where am I going wrong? – r0bb077 Mar 6 '12 at 22:41
You need to use end instead of End. – Kyle Jones Mar 6 '12 at 23:53
Sorry Kyle, still getting the same thing?! – r0bb077 Mar 7 '12 at 0:17

As suggested, use an editor to write shell scripts.

Here the corrections to your edited version:

You need to write set n=0 instead of n=0 to get rid of the "command not found" error message,

foreach sql ( *_*.sql ) instead of foreach sql *_*.sql

and end instead of End.

You need normal quotes " instead of to quote the parameters for sed.

share|improve this answer
Hi Jofel, thanks for your input but I still seem to be getting exactly the same error message after your changes. I've edited my post again with what I have – r0bb077 Mar 7 '12 at 0:12
@r0bb077 see the answer from Keith Thompson – jofel Mar 7 '12 at 8:46

Your Answer


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.