命令行 脚本入门

为什么要学命令行?

  • 如果你是一个小白,学习命令行,可以让你入睡。
  • 如果你是一个电脑玩家,学习命令行,可以让你装逼事半功倍。

点击展开👉破除恐惧的良方

好了,命令行难不难?俗话说,万事开头难,克服的就是心理、语言障碍后,再看完这篇入门教程后,你会觉得满简单的。此视频可破除恐惧👇

其实会点命令行才能破除恐惧,之前做的视频👇:

看完视频后,你应该大概明白命令行的操作感受了,继续向下,文字版内容更丰富。

啥是命令行

大家经常使用的叫做图形界面(GUI)。

而命令行就是形如下面的字符界面(CUI,CLI):

Command-Line Interface, 图示为PuTTY

▲Command-Line Interface, 图示为PuTTY

  • Windows工具为CMD,PowerShell,Windows Terminal
  • *nix类系统上为Bash
  • Mac上则为Zsh(之前也为Bash),终端

不管是图形界面还是字符界面,其目的都是为了方便你使用操作系统。图形界面的方便在于直观,可视化。命令行的方便在于精确和掌控感。 将分别介绍Bash,CMD及Powershell。

先来区分几个概念。

脚本

脚本(script)就是存放命令的文本文件。

在*nix平台,脚本一般后缀为sh。
在Windows平台中,CMD脚本称为批处理文件,后缀为bat;Powershell脚本后缀为ps1。

Shell

shell就是脚本运行程序
也就是说,shell 用来运行脚本

  • shell 可以一条一条地交互式运行用户指令(用户输一个,shell 跑一个)
  • shell 也可以执行脚本中的命令 (shell 跑完一个文件中的所有命令)
  • 在脚本中,可以定义函数、变量、条件判断等语句,所以写脚本也是编程

点击展开👉一般shell可以配置

常见的shell:Zsh、Bash,他们都可以自由配置。

比如用户的配置文件 ~/.Bashrc

#! 表明了文件类型,此处是一个脚本,紧跟着的是脚本解释器的声明,如
#! /bin/sh

终端,Terminal

终端是上古电脑的一个概念。以前电脑都是用于科学计算,所以一个主机会分出多套屏幕键盘和鼠标。这一套套键鼠屏幕,构成了一个终端。

所谓终端,就是使用计算机的客户端。

现在的终端已经变成了一个程序,用来容纳shell。比如SSH、Windows Terminal,以及macOS的终端

命令行基本语法

无论是Bash,CMD抑或是Powershell,命令的基本结构都是:

command option # 也就是: 命令+选项参数

command可能是:

1、shell内置命令,比如Bash的cd
2、系统提供的程序/脚本,linux中,这些程序通常存在于/bin,/usr/bin 目录中
3、外部程序:工作目录中的脚本(用户手写/下载)和二进制程序、PATH变量中的程序

只要把程序放在PATH变量对应的目录中,程序就可以直接在shell 中运行,
否则,你就需要输入程序的完整路径才能运行。

option是选项/参数

它是用于修改、确定command行为的。option可以很简单,简单到可以省略不写;也可以非常复杂,复杂到阅读起来很吃力。

ls #显示目录内文件
ls -l #显示目录内文件的详见信息,包括日期、大小
firewall-CMD --permanent --zone=public --list-ports

总之,在shell中,你可以运行各种程序,还可以通过各种参数控制程序行为。

Bash/Zsh - *nix 下的命令行

替换

替换是非常重要的命令行概念,在执行命令前,先将部分命令替换成值或结果,然后执行命令。这里以*nix为例,CMD 和PS 也有替换的概念。

比如说,你需要多次使用iPhone 的名称,但是你觉得打字不太方便,你就可以把这窜字符存到变量中:sj=iPhone。等你下次需要使用,比如在窗口打印“iPhone”字符的时候,可以直接敲打命令:echo $sj

变量的值替换变量名,这是最常见的一种替换。

变量替换

  • 变量的定义为:name=value,=号旁不能有空格
  • 变量的使用,需要在名称前添加美元符号:$vname (或者${vname},这个形式也非常好用)
  • 变量的修改:变量名=新值,sj=Xiaomi

使用变量时,命令在执行前,会把变量先变成变量存储的值。

address=https://manyouit.com 
curl $address

执行过程:

  1. 先把$address 变成https://manyouit.com
  2. 执行curl https://manyouit.com
变量与引号

由于Bash 中,某些字符有特殊的意思。如何使用这些特殊字符? ——使用引号。

address=https://manyouit.com 
curl '$address' # 程序错误,因为没有$address这样的网址;亦即“变量替换”失效
curl "$address" # 成功;双引号不会使得“变量替换”失效

使用单引号(英文),可以使大部分特殊符号失效;使用双引号(英文),不会使特殊符号失效。

执行结果替换,命令替换

先执行内部命令,然后结果作为新命令的一部分。
两种形式:

`inner command`
$(inner command)

address=https://manyouit.com/
echo `echo $address`
$(echo $address)

CMD: REM 括号有类似功能
set a=(cmd)

数学运算表达式替换:$(()),$[]

echo $[1+2] #3
echo $((1+2)) #3 ,$(()),$[]等效

支持+ - * / %:分别为 “加、减、乘、除、取模”等运算。但是注意,Bash只能作整数运算。

进程替换与管道

进程替换:
将(多个) 命令/进程的输出存储成文件,然后作为当前命令新的组成部分;
或者将当前命令的输出成文件,作为新命令的输入。

文件替换

$(<filename) 
`<filename`

读取文件内容组成新命令 。

替换:变量 vs 命令 vs 文件 vs 进程 vs 管道

# 变量替换:先取变量值,用值重新组成命令后执行。
echo ${PATH#*:}   # 变量值替换(不修改变量本身),此处使用模式 *: 移除变量中部分

# 命令替换:先执行内部命令,用执行输出内容重新组成命令后执行。
ls -ld `locate which` # ls -ld $(locate which) 这种方法兼容性较差。

# 进程替换:先执行部分命令,用执行输出内容成文件后,**文件名**重新组成命令后执行。
comm <(ls -l) <(ls -al)
cat a.txt >(cat >b.txt)

# 文件替换:先读取文件内容,用读取的内容重新组成命令后执行。

# 管道: 前一个命令执行的`stdout 成为后面命令的stdin`
CMD1 | CMD2 | CMD3

PowerShell - 微软新一代命令行

字面值:

  • 数字:123
  • 字符串:"good"'she says, "amazing"'
  • 对象

输出值:

对于数字字符串,在命令行处直接输入值,然后Enter即可输出
对于变量,在命令行处直接输入值,然后Enter即可输出
逗号来输出多个值,每一个值都会还行显示:$a,3

变量,美元字符开头$Var1

声明变量:

$Var1="good #等于号之前允许一个空格"或者

$aNumber = 5 -as [double]
$aList = 1,2,3,4,5
$aString = $aList -join '--' # 也可以用-split来分离
$aHashtable = @{name1='val1'; name2='val2'}

echo $aString
echo "Interpolation: $aString" #双引号内可以解析变量
echo "$aString has length of $($aString.Length)" #变量可以包括在$()中,$()用来解析变量
echo '$aString' #单引号内不可以解析变量
echo @"
This is a Here-String
$aString
"@
# 双引号 Here-String 及解析变量
# 可以用单引号来声明Here-String ,此时无法解析变量
变量和赋值=顺序,$a=CMD argu… 先执行再赋值

CMD - 微软上一代命令行

CMD程序中文名称为命令提示符。它的脚本文件格式为.bat,也称批处理。

变量与%(百分号)

  • %变量%,会把变量的结果作为命令的一部分,(类似Bash 变量替换)
  • 在命令行界面和批处理文件(.bat 后缀文件)里,变量形式为%Name%
  • 在for 语句中的临时变量
    • 命令行用%Name
    • 批处理文件用%%Name
  • 特殊表示,在批处理文件中%0-%9 用来处理程序的参数输入

对比与区别

命令组合、分隔符

对*nix 有效

command1 ; command2 #不管command1是否执行成功都会执行command2;顺序执行
command1 && command2 #只有command1执行成功后,command2才会执行,否则command2不执行
command1 || command2 #command1执行成功后command2 不执行,否则去执行command2

对Powershell 有效

command1 ; command2 #顺序执行
(command1) -and (command2) #相当于*nix 的 &&,但只能输出错误和Bool值,没有命令输出
(command1) -or (command2) #相当于*nix 的 ||,但只能输出Bool值

对CMD 有效

:: 顺序执行 
command1 & command2 
:: 执行成功才执行 
command1 && command2 
:: 执行失败才执行 
command1 || command2 
:: 包裹命令 
(command1) 

::逗号、分号相当于空格:`dir,c:\ `  
::一个命令需要使用过个参数运行多次,则使用:
dir C:\;D:\

变量与环境变量,*nix与Windows

点击展开👉

在给xiaogpt做commit时,特意区分了环境变量的写法。

系统和Shell Linux *sh Windows CMD用户 Windows PowerShell用户
1、安装包 pip install miservice_fork pip install miservice_fork pip install miservice_fork
2、设置变量 export MI_USER=xxx
export MI_PASS=xxx
set MI_USER=xxx
set MI_PASS=xxx
$env:MI_USER="xxx"
$env:MI_PASS="xxx"
3、取得MI_DID micli list micli list micli list
4、设置MI_DID export MI_DID=xxx set MI_DID=xxx $env:MI_DID="xxx"

列出当前shell(继承/复制自系统)的环境变量

系统和Shell Linux *sh Windows CMD用户 Windows PowerShell用户
示例 env set ls env:

nix环境下,set会输出当前shell 的设置。
在Linux/macOS环境下,env还有设置变量并运行的作用

创建当前shell的环境变量并暴露给子shell

系统和Shell Linux *sh Windows CMD用户 Windows PowerShell用户
示例 export x=v set x=v $env:x="v"
说明 export 的作用是将变量暴露给子shell cmd中set设置的环境变量自动暴露给子shell $env:xxx设置的环境变量自动暴露给子shell

注意powershell 中也有set命令,它的语法是set xname xvalue
powershell 的set设置的是当前shell 的变量,不会暴露给子shell。

创建当前shell的环境变量并不暴露给子shell

系统和Shell Linux *sh Windows CMD用户 Windows PowerShell用户
暴露 export x=v set x=v $env:x="v"
不暴露 x=v undefined set x v
$x=v

上两种创建环境变量不会修改系统级别或者用户级别的环境变量。

删除当前shell的环境变量

系统和Shell Linux *sh Windows CMD用户 Windows PowerShell用户
推测会暴露给子shell unset x= set x= $env:x=""

修改系统环境变量

系统和Shell Linux *sh Windows
CMD用户
Windows
PowerShell用户
示例 - setx x v setx x v
说明 undefined setx 会写入注册表 setx 会写入注册表

修改系统环境变量后,重新打开新shell方可观察变化。

列出shell中的单个变量或者环境变量

系统和Shell Linux *sh Windows
CMD用户
Windows
PowerShell用户
shell内定义的 echo $x echo %x% echo $x
继承自环境的 printenv PATH set x echo $env:path
说明 export x=v
这种变量可以printenv x
不区分来自环境还是内部。
可互换
-

注释方法

注释是一种对脚本的标注。

行首注释需要将注释符号放在行首。
CMD/bat的行首注释形式:
rem 注释注释
或另一种:
:: 注释注释

行内注释,注释符号不需要放在行首。
CMD/Bat的行内注释形式:&:: 行内注释

Bash使用“#”符号注释:# 注释注释

PowerShell# 注释注释
文档:<# 注释注释 #>

换行输入命令

命令太长时,容易造成阅读障碍,比如创建任务计划的触发器时:

trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -hours 24)

确实,难以阅读与理解,而只要在行末,添加`就能实现换行输入命令:

$trigger = New-ScheduledTaskTrigger `
    -Once `
    -At (Get-Date) `
    -RepetitionInterval (New-TimeSpan -Minutes 5) `
    -RepetitionDuration (New-TimeSpan -hours 24)

行末添加的符号为转义字符,它可以改编字符原来的意思。在这里,输入转义符好后,再键入Enter键,会产生一个新行,但执行的时候,实际上换行会被当成空白

Powershell的换行转义符为`,另外,CMD的转义符号是^,*nix是\

常用命令

常用*nix命令

lsof -i:10086  #[查看端口占用](https://linux.cn/article-4099-1.html):  
ln Source Link #制作连接   
netstat -anp|grep 80 #端口占用   
perl -p -i -e "s/\r//g" filename #删除CR(Windows换行符有CRLF)
# 查找命令位置
which

# CentOS系统
# 防火墙:firewalld
# 设定开机启动、禁用防火墙
systemctl enable firewalld
systemctl disable firewalld
# 开启、关闭防火墙
systemctl start firewalld
systemctl stop firewalld

# 检查状态:
firewall-cmd --state
# 设定:https://www.jianshu.com/p/411274f96492
port=1313
firewall-cmd --permanent --add-port=$port/udp
firewall-cmd --permanent --add-port=$port/tcp
# 常用
firewall-cmd --permanent --query-port=80/tcp  
# 列出打开端口,查看端口占用
firewall-cmd --list-ports #--permanent --zone=public 
firewall-cmd --reload

常用Windows命令(此处为PS注释法)

findstr #查找字符串
nslookup -qt=A manyou.it ns-uk.topdns.com  #DNS解析
powercfg -devicequery wake_armed #查看唤醒电脑的硬件
nslookup baidu.com 240C::6644 #使用特定服务器解析域名

# 设置代理:
set HTTP_PROXY=192.168.0.7:1080
set HTTPS_PROXY=192.168.0.7:1080

# 查找命令位置
where.exe

# 防火墙禁止访问(PS 写法)
netsh advfirewall firewall add rule name="IP Block" `
dir=out `
interface=any action=block remoteip=20.84.22.197,104.18.156.232,104.18.157.232,2606:4700::6812:9de8,2606:4700::6812:9ce8

# 查看hardlink
fsutil.exe hardlink list path\to\file

PowerShell命令

# 查找命令位置
Get-Command
echo $PSVersionTable #PS版本
certutil -hashfile	 #计算md5   
Get-ScheduledTask | where {$_.settings.waketorun} #查看唤醒电脑的计划任务  
Netstat -ano|findstr "8080" #查看占用某个端口的进程  
Get-Command -Module PSScheduledJob | Group-Object Noun #[分组](https://www.pstips.net/about-scheduledjob.html#comment-18118),获得命令,然后分组(on Noun)  
[console]::beep(500,300) #蜂鸣
set #设置变量值与cmd 同名但不同程序

New-Item -ItemType SymbolicLink -Path "Link" -Target "Source" # 创建文件的符号链接,需要管理员, 简写ni
ni -ItemType hardlink "X:\music\fav\美若黎明.flac" -target "X:\music\李健 - 李健 2015 - FLAC\02. 美若黎明.flac"

# 复制文件到目录
Copy-Item "C:\Wabash\Logfiles\mar1604.log.txt" -Destination "C:\Presentation"

CMD 命令

::打印所有变量;设置变量值
set
::查找程序位置
for %i in (cmd.exe) do @echo.   %~$PATH:i


::windows地址栏使用`\`而不是`/`  
::制作目录软连接:
mklink /D Link Source 

::制作文件软连接
mklink Link Source 

三方程序记录

# frp
./frps -c ./frps.ini #有标准输出
nohup ./frps -c ./frps.ini &
pip install --upgrade name # 更新pip包
java -version  # 查看版本

2020-01-05 scripts 脚本 cmd powershell 命令行 批处理 bat cui cli gui 脚本 shell sh zsh bash

相关文章