一、前言

    由于工作中,也维护着部分Windows Server 服务器,命令行操作还是经常需要用到的,把一些非常有用但是又不不是太经常使用的命令总结。


二、 for 语句

    首先,我们来看一下 for 语句的基本语法格式:

在cmd 窗口中: for %i in (SET) do command 

在批处理文件中:for %%i in (SET) do command

    之所以要区分 cmd 和批处理文件两种环境,是因为在这两种环境下,命令语句表现出来的行为虽然基本一样,但是在细节上还是稍有不同,最明显的一个差异就是: 在 cmd 窗口中, for 之后的变量 i 必须使用单百分号引用, 即 %i 。 而在批处理脚本文件中,引用变量必须使用双百分号引用,即 %%i 。 为了方便起见,若不是特别强调,以下的讲解都以批处理文件环境为例。

    当在 batch 脚本中使用 FOR 命令时, 必须使用 %%variable 替代 %variable。 而且, variable 名称是大小写敏感的,所以 %i  和 %I 是不同的。


我们先来看一下 for 语句中的基本要素都有些什么

1、 for , in 和 do 是 for 语句的关键字,它们三者缺一不可。

2、 %%i 是for 语句中对形式变量的引用,就算它在 do 后的语句中没有参与语句的执行,也是必须出现的。

3、 in 之后, do 之前的括号不能省略。

4、 SET 表示字符串、变量或者文件名,可以使用通配符,  command 表示命令语句。

5、 for 命令可以接受选项,  /f  、 /r  、 /l 、/d 选项。


for 语句的注意事项以及工作原理:

1、for 语句中的形式变量 i , 可以替换为 26个字母表中的任意一个字符, 变量名区分大小写。也就是说,%%I 和%%i 会被认为不是同一个变量;形式变量 I还可以换成其他的字符,但是,为了不与批处理中的%0~%9 这10 个形式变量发生冲突,请不要随意把%%I 替换为%%0  ~%%9 中的任意一个;

2、in 和do 之间的 SET 表示的字符串、文件名或变量可以是一个,也可以是多个,每一个字符串或变量,我们称之为一个元素,每个元素之间,用空格键、跳格键、逗号、分号或等号分隔;

3、for 语句依次提取 SET  中的每一个元素,把它的值赋予形式变量 %%i , 带到do 后的command 中参与命令的执行;并且每次只提取一个元素,然后执行一次 do 后的命令语句,而无论这个元素是否被带到 command 中参与了运行;当执行完一次do 后的语句之后,再提取 SET 中的下一个元素,再执行一次 command,如此循环,直到 SET 中的所有元素都已经被提取完毕,该for 语句才宣告执行结束;


其中,第3 点是最为关键的,它描述了for 语句的执行过程,是for 语句的精髓所在,大家一定要牢记这一条,才能深刻理解更为复杂的for 流程。


下面来看几个例子:

@echo off

for %%i in (one, two, three) do echo %%i

pause

for 命令每一次从 SET 集合中取出一个元素(元素之间通过空白符【tab, 空格或其组合】、逗号、等号作为分隔符), 赋值给 %%i 变量。一直循环,直到 SET 集合中的元素被取完。


(一)  为解析文本而生:for  /f  的基本用法 

    提取文本信息,是for /f 的拿手好戏:读取文件内容;提取某几行字符;截取某个字符片段;对提取到的内容再切分、打乱、杂糅只要你所能想到的花样,for /f  都会想方设法帮你办到,因为,for /f  就是被设计成专门用于解析文本的。 

## a.txt
chrome,firefox,safari
mac,windows,linux

## test.bat
@echo off
for /f %%i in (a.txt) do echo %%i
pause

for 语句依次读取 a.txt 的每一行,作为一个元素赋值给 %%i。也就是说, for /f 默认情况下是以行为单位处理文件内容。 


(二)  设定分隔符,切分文本行: delims=

@echo off
for /f "delims=," %%i in (a.txt) do echo %%i
pause

再次运行,看到什么变化了吗? 只打印出了逗号 【,】 前的一个元素。

在这里,我们引入一个选项, "delims=" 用于指定读取到的行以什么作为分隔符,分割为元素。当然,可以同时指定多个分隔符号: "delims=,|-:" 。如果没有指定 "delims=" ,那么 for /f 默认以空白字符(空格、TAB)序列作为分隔符。

    如果我们要打印出除了第一列之外的其他元素,该怎么办呢?


(三)  按需提取元素: tokens=NUM

    tokens=x,y,m-n  用于指定提取哪一个字段的数据, NUM 有多种表示形式: 单个数字,即 tokens=2 ; 多个非连续的域,即 tokens=1,3,5;  连续的域, 即 tokens=1-4。

@echo off
for /f "tokens=3 delims=," %%i in (a.txt) do echo %%i
pause

如果我们想一次提取多个字段呢? 那么聪明的你就会想到 tokens=1,3 , ok 

@echo off
for /f "tokens=1,3 delims=," %%i in (a.txt) do echo %%i
pause

执行后,你会发现,为什么只显示了第一列的数据?j_0070.gif  蒙圈了吧


原来,echo  后面的  %%i  只接收到了  tokens=1,3  中第一个数值1所代表的那一列数据,而第二个数值3 所代表的这一列数据因为没有变量来接收,所以就无法在执行结果中显示出来了。 

那么,要如何接收  tokens=  后面多个数值所指代的内容呢? 

for /f  语句对这种情况做如下规定: 

     如果  tokens=  后面指定了多个数字,如果形式变量为%%i,那么,第一个数字指代的内容用第一个形式变量%%i 来接收,第二个数字指代的内容用第二个形式变量%%j 来接收,第三个数字指代的内容用第三个形式变量%%k 来接

收。第N 个数字指代的内容用第N 个形式变量来接收,其中,形式变量遵循字母的排序,第 N 个形式变量具体是什么符号,由第一个形式变量来决定:如果第一个形式变量是%%i,那么,第二个形式变量就是%%j;如果第一个形式

变量用的是%%x,那么,第二个形式变量就是%%y。 


好了, 有了上面的概念, 我们就可以很好的解决刚才的 bug 了。

@echo off
for /f "tokens=1,3 delims=," %%i in (a.txt) do echo %%i %%j
pause

tokens 支持多种形式

tokens=1
tokens=1,3
tokens=1-3
tokens=1-3,7
tokens=1,3-5
还有一种比较怪异的写法

tokens=1,*

其中奥妙就在这个星号上面。 

    tokens=后面所接的星号具备这样的功能:字符串从左往右被切分成紧跟在[ * ]之前的数值所表示的字段之后,字符串的其余部分保持不变,整体被*所表示的一个变量接收。 

    是不是很绕,不好理解, 来看个实例就好了。

@echo off
for /f "tokens=1,* delims=," %%i in (a.txt) do echo %%i %%j
pause

【输出】
chrome firefox,safari
mac windows,linux

理解: 根据delims指定的分隔符对文本行进行切分,tokens=1,* 当切完第一列之后,发现 tokens=1,* 。 1后面跟着 * ,所以就不再进行切分了,整体作为第二列,然后分别传递给 %%i, %%j 变量。


(四)  直奔主题: skip=N

for  /f  允许你跳过无用的行,直接从第N+1 行开始处理,这个时候,就需要使用选项  skip=N,其中,N 是一个正整数,表示要跳过的行数。


(五)  视而不见: eol=CHAR

for /f 允许你跳过某些不想处理的行,只处理有用的数据。这时,就需要使用选项 eol=CHAR。 忽略以指定 CHAR 字符打头的行。

for /f  语句是默认忽略以分号打头的行内容的,正如它默认以空白符作为字符串的切分字符一样。 


(六)  执行多条命令

@echo off
for /f "tokens=1,* delims=," %%i in (a.txt) do (
command1
command2
...
)

pause


破译了天机:usebackq  是一个增强型参数,当使用了这个参数之后,原来的for语句中第一个括号内的写法要做如下变动:如果第一个括号里的对象是一条命令语句的话,原来的单引号'要改为后引号`;如果第一个括号里的对象是字符串的话,原来的双引号"要改为单引号';如果第一个括号里的对象是文件名的话,要用双引号"括起来。 


三、 net 语句

(一)  利用 net user 命令添加、删除系统本地用户

## 添加用户
net user user_name [user1_passwd] /add 
    /active:no          禁用用户 
    /active:yes         激活用户 
    /passwordchg:yes    用户可以改变密码 
    /passwordreq:yes    用户必须拥有密码 
    /expires:never      帐户永不过期,而不是指密码不过期

## 添加用户组
net localgroup group_name /add


## 把用户添加到组
net localgroup group_name user_name /add

## 把用户从组中删除
net localgroup group_name user_name /del

## 删除用户
net user user_name /del 

常用的例子:
1 添加一个用户到一个组 net localgroup admin 123 /add
2 从一个组删除一个用户 net localgroup admin 123 /del
3 net localgroup 列出本地所有用户组
4 net localgroup administrators  列出特定组的用户

## 批量删除
@echo off
for /f %%i in (user_del.txt) do (
net localgroup group_name %%i /del
net user %%i /del
)


四、 cmd 命令执行时,如何实现 自动选择 y 的做法

(一)  利用  /y 选项

net stop mssqlserver /y




参考:

http://blog.csdn.net/wh_19910525/article/details/7912440