C Shell 是一种非常经典的 Unix/Linux Shell,由 Bill Joy 在 BSD 系统中开发,它的语法与更早的 Bourne Shell (sh) 有很大不同,引入了一些在当时看来很创新的功能,比如命令历史、别名和更复杂的脚本语法。

虽然现在更流行的是 Bash (Bourne-Again SHell),但了解 C Shell 对于阅读旧系统脚本、理解 Shell 的发展历史以及在特定环境中工作都非常有帮助。
C Shell 的基本概念
在开始命令之前,先理解几个核心概念:
- 提示符:C Shell 的默认提示符通常是 ,这与 Bash 的 不同,是识别你当前在哪种 Shell 下的一个简单方法。
- 命令历史:C Shell 会记住你之前输入的命令,使用 可以重复执行上一条命令。
- 别名:你可以为长或复杂的命令创建简短的别名。
alias ll 'ls -la'。 - 脚本文件:C Shell 脚本通常以
.csh或.sh作为文件后缀。
常用交互式命令
这些命令通常在终端中直接输入使用。
文件和目录操作
| 命令 | 全称 | 描述 | 示例 |
|---|---|---|---|
ls |
list | 列出目录内容 | ls -la (列出所有文件,包括隐藏文件) |
cd |
change directory | 切换当前目录 | cd /tmp (切换到 /tmp 目录) |
pwd |
print working directory | 显示当前所在目录的完整路径 | pwd |
mkdir |
make directory | 创建新目录 | mkdir my_project |
rmdir |
remove directory | 删除一个空目录 | rmdir empty_dir |
cp |
copy | 复制文件或目录 | cp file1.txt file2.txt (复制文件) |
mv |
move | 移动文件或目录,也用于重命名 | mv old_name.txt new_name.txt (重命名) |
rm |
remove | 删除文件 | rm unwanted_file.txt |
touch |
- | 创建一个空文件或更新文件时间戳 | touch new_file.txt |
查看和编辑文件
| 命令 | 全称 | 描述 | 示例 |
|---|---|---|---|
cat |
concatenate | 显示整个文件的内容 | cat my_log.txt |
less |
- | 分页显示文件内容,可以上下翻页 | less long_file.txt (按 q 退出) |
more |
- | less 的前身,功能较少 |
more long_file.txt |
head |
- | 显示文件的开头几行 (默认10行) | head -n 20 my_log.txt |
tail |
- | 显示文件的结尾几行 (默认10行) | tail -f my_log.txt (实时追踪文件变化) |
文本搜索和处理
| 命令 | 全称 | 描述 | 示例 |
|---|---|---|---|
grep |
global regular expression print | 在文件中搜索匹配的文本行 | grep "error" my_log.txt |
find |
- | 在目录树中查找文件 | find . -name "*.c" (在当前目录下查找所有 .c 文件) |
wc |
word count | 统计文件的行数、单词数和字节数 | wc my_report.txt |
进程管理
| 命令 | 全称 | 描述 | 示例 |
|---|---|---|---|
ps |
process status | 显示当前运行的进程 | ps aux (显示所有用户的详细进程列表) |
kill |
- | 发送信号给进程,通常用于终止进程 | kill 12345 (终止进程ID为12345的进程) |
jobs |
- | 显示当前 Shell 会话中后台运行的作业 | jobs |
bg |
background | 将一个暂停的作业放到后台运行 | bg %1 (将作业1放到后台) |
fg |
foreground | 将一个后台作业调到前台运行 | fg %1 (将作业1调到前台) |
C Shell 特有的功能和语法
这部分是 C Shell 与 Bash 等其他 Shell 区别最大的地方。

命令历史和重新调用
- 重复执行上一条命令。
% ls -l % !! ls -l # 会再次执行 ls -l
!n:执行历史记录中的第n条命令。% !3 # 执行历史记录中的第3条命令
!string:执行以string开头的最近一条命令。% grep "hello" file.txt % !g # 会再次执行 grep "hello" file.txt
别名
使用 alias 命令创建和查看别名。
% alias ll 'ls -alF' # 创建一个 ll 别名 % ll total 16 drwxr-xr-x 2 user user 4096 Jan 10 10:00 ./ drwxr-xr-x 10 user user 4096 Jan 10 09:58 ../ -rw-r--r-- 1 user user 0 Jan 10 10:00 file.txt % alias # 查看所有已定义的别名 ll ls -alF
要永久保存别名,需要将其添加到 ~/.cshrc 文件中。
变量
C Shell 的变量分为两种:
-
C Shell 变量 (局部变量):使用
set命令设置,仅对当前 Shell 及其子进程有效。
(图片来源网络,侵删)% set my_name = "Alice" % echo $my_name Alice
-
环境变量 (全局变量):使用
setenv命令设置,对所有子进程都有效。% setenv PATH "$PATH:/my/custom/path" # 将路径添加到环境变量PATH中 % echo $PATH /usr/bin:/bin:/my/custom/path
重要区别:
set var = value(等号两边有空格)setenv var value(等号两边没有空格)
条件判断 (if)
C Shell 的 if 语法比较独特,使用 then 和 endif。
#!/bin/csh
# 检查是否传入了参数
if ($#argv == 0) then
echo "错误:请提供一个文件名作为参数。"
exit 1
endif
# 检查文件是否存在
if (-e $1) then
echo "文件 $1 存在。"
if (-f $1) then
echo "并且它是一个普通文件。"
endif
else
echo "文件 $1 不存在。"
endif
$#argv:表示参数的个数。$1:表示第一个参数。-e:判断文件或目录是否存在。-f:判断是否是一个普通文件。
循环 (foreach 和 while)
-
foreach循环:遍历一个列表。#!/bin/csh foreach file (*.txt) # 遍历当前目录下所有 .txt 文件 echo "正在处理文件: $file" # 对 $file 进行操作... end -
while循环:在条件为真时重复执行。#!/bin/csh set count = 0 while ($count < 5) echo "Count is $count" @ count++ # C Shell 中使用 @ 进行算术运算 end- 用于算术运算,如
@ count = $count + 1。
- 用于算术运算,如
C Shell 脚本示例
这是一个简单的备份脚本 backup.csh:
#!/bin/csh
# 检查是否提供了源目录和目标目录参数
if ($#argv != 2) then
echo "用法: $0 <源目录> <目标目录>"
exit 1
endif
set src_dir = $1
set dest_dir = $2
# 检查源目录是否存在
if (! -d $src_dir) then
echo "错误: 源目录 '$src_dir' 不存在。"
exit 1
endif
# 创建目标目录(如果不存在)
if (! -d $dest_dir) then
echo "创建目标目录 '$dest_dir'..."
mkdir -p $dest_dir
endif
# 执行备份 (使用 cp -r 递归复制)
echo "开始备份从 '$src_dir' 到 '$dest_dir'..."
cp -r $src_dir/* $dest_dir/
if ($status == 0) then
echo "备份成功完成!"
else
echo "备份失败!"
exit 1
endif
如何运行脚本:
- 保存文件:将上面的代码保存为
backup.csh。 - 赋予执行权限:
chmod +x backup.csh。 - 运行脚本:
./backup.csh /path/to/source /path/to/destination。- 注意:强烈建议使用
#!/bin/csh作为 shebang,而不是#!/bin/sh,因为sh可能不是 C Shell。
- 注意:强烈建议使用
C Shell vs. Bash
| 特性 | C Shell (csh/tcsh) | Bash (bash) |
|---|---|---|
| 提示符 | (默认) | (默认) |
| 变量赋值 | set var = value (有空格) |
var=value (无空格) |
| 环境变量 | setenv var value (无空格) |
export var=value |
| 算术运算 | @ var = $var + 1 |
$((var++)) 或 let var++ |
| 条件判断 | if (...) then ... else ... endif |
if [ ... ]; then ... fi |
| 循环 | foreach ... end / while ... end |
for ... do ... done / while ... do ... done |
| 命令替换 | `command` (反引号) | $(command) (推荐) |
|
| 数组 | 不支持原生数组 | 支持 arr=("a" "b" "c") |
| 流行度 | 早期 BSD 系统,现已较少作为默认 Shell | Linux 和 macOS 的默认 Shell,绝对主流 |
虽然 C Shell 已经不是主流,但它的很多思想(如命令历史、别名)被后来的 Shell 继承和发展,理解 C Shell 的语法,特别是它独特的 if-then-endif、foreach 和 set/setenv 机制,能帮助你更好地理解 Shell 脚本的历史和多样性,如果你需要在古老的 Solaris、BSD 系统或某些特定设备上工作,C Shell 仍然是一个必须掌握的工具。
