Sign in to follow this  

Understanding a shellscript

This topic is 3201 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, so I've got this shell script. I understand what it does, I'm just having trouble understanding some of it. I've tried googling some of the stuff, but I haven't stumbled upon anything to useful in this context anyway. Here's the script: #!/bin/tcsh set n = 0 foreach f ( * ) echo $f | grep " " if ( $? == 0 ) then mv "$f" `echo $f | sed -e "s/ /_/g"` @ n += 1 endif end echo $n changed Ok, so it uses the tcsh shell. Then it creates a variable n and initialises it to 0. It goes each file in the directory and picks out the files with a space in it's name. It then renames the file, replacing each space with an underscore and then it finally returns how many files it changed. I just need clarification on how a few things work. Firstly, what specifically does the set keyword do? Is it just a more explicit way of initializing a variable? Since I've seen scripts with just n = 0 without the keyword set. Also, since f isn't declared, I assume it's like some sort of special variable in UNIX that refers to a file. Although I'm not sure what the ( * ) represents. Similarly, I have no clue what $? represents. And typing that into google, gave me all manner of crap lol. I'd appreciate any help on this one guys. Cheers

Share this post


Link to post
Share on other sites
hey, I'm definitely no expert (or even know much about shell scripts). I can't answer all of your questions but generally * means wild card. so in this instance i believe it means any file with any name.

you can use a "wild card" in any string such as *_3.13.09 would mean any string (or in the case of your script any file) that ends in _3.13.09

now that i'm looking at your script I believe the "foreach f(*)" IS the line that is initializing f. you could test this buy replacing f with another letter or name. the (*) means a file name.

I hope this helps a little, like I said before I am definitely no expert and there is a good chance that some or all of the info I gave is incorrect.

Share this post


Link to post
Share on other sites
The variable $? contains the exit status of the last command. If you are familiar with C or C++ the exit status is the value that main() returns, or passed to the library function exit(int).

In this case the command is the execution of "grep". Looking at some documentation for grep, it says (under DIAGNOSTICS):
Quote:

Normally, exit status is 0 if selected lines are found and 1 otherwise.
But the exit status is 2 if an error occurred, unless the -q or --quiet
or --silent option is used and a selected line is found.


This means that the commands inside the if block are run only if the exit value is 0, that is when a space was located in the filename.

if ( $? == 0 ) then
mv "$f" `echo $f | sed -e "s/ /_/g"`
@ n += 1
endif

Share this post


Link to post
Share on other sites
#!/bin/tcsh
Run a tcsh script
set n = 0
declare a local int variable n and initialize it to zero
foreach f ( * )
iterate over every file in the current working directory that does not being with a dot
  echo $f | grep " "
send the file name through grep searching for a space character
  if ( $? == 0 ) then
if one or more space characters was found,
    mv "$f"  `echo $f | sed -e "s/ /_/g"`
rename the file replacing all the space characters with underscores
    @ n += 1
increment the counter
  endif
close the if-scope
end
close the foreach-scope
echo $n changed
print the number of renamed files

You could of course write this more concisely in POSIX shell.

n=0
for f in *; do
grep -q ' ' $f && mv $f $(echo $f | tr ' ' _)
$((++n))
done
echo $n changed


What the script does id rename every non-hidden fil in the current working directory to replace all spaces with underscores.

Share this post


Link to post
Share on other sites
Wow thanks for the replies guys.

Just a couple of questions:

1. Is there any special significance of the keyword set?
2. From your replies, I assume that f is a sort of pointer to a file and that $f is the filename. Is that correct?
3. Is there any special signifance of the @ character in the line @ n += 1?

Cheers

[Edited by - raydey on March 14, 2009 9:03:00 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by raydey
1. Is there any special significance of the keyword set?

As far as I recall, and it's been over a decade since I used tcsh, it declares n as an integer-valued variable.
Quote:
2. From your replies, I assume that f is a sort of pointer to a file and that $f is the filename. Is that correct?

No. f declares the variable and assigns a value to it (it's an lvalue). $f gets the rvalue of the variable. $f is a string, the string is the name of the file. Unix shells are text-manipulation languages.

In your example, foreach f (*) is the equivalent of the C++ expression

for (std::string f = string_list.start(); f != string_list.end(); f = string_list.next()) { ... }
where string_list is some non-standard container that yields a sequence of strings.
Quote:
3. Is there any special signifance of the @ character in the line @ n += 1?
Yes. It's a tcsh shortcut saying the following expression should be interpreted as an arithmetic expression. It's like the POSIX shell construct $(( ... )).

Share this post


Link to post
Share on other sites
Sign in to follow this