shell命令 按功能 - zhongjiajie/zhongjiajie.github.com GitHub Wiki

shell命令-按功能

shell基础

配置相关

避免删除 复制 移动命令的误操作

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

source global definitions

if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

设置环境变量

  • PATH=$PATH:/path/to/bin: 控制台中设置,不赞成这种方式,因为他只对当前的shell 起作用,换一个shell设置就无效了
  • 修改/etc/profile文件export PATH="$PATH:/NEW_PATH"如果你的计算机仅仅作为开发使用时推存使用这种方法,因为所有用户的shell都有权使用这个环境变量,可能会给系统带来安全性问题。这里是针对所有的用户的,所有的shell
  • 修改~/.bashrc文件export PATH="$PATH:/NEW_PATH":可以把使用这些环境变量的权限控制到用户级别,这里是针对某一特定的用户,如果你需要给某个用户权限使用这些环境变量,你只需要修改其个人用户主目录下的 .bashrc文件就可以了

修改主机名

  • centos7 or ubuntu: hostnamectl status查看主机名相关命令,sudo hostnamectl --static set-hostname <host-name>永久修改主机名,不需要重启,注销重新登录就能看到主机名变化了

链接

ln -s src dest: 在dest建立src的软连接,src文件丢失会影响dest文件 ln src dest: 在dest建立src的硬链接,src和dest的各项属性相同

shell脚本的特殊参数

符号 含义
$0 shell脚本名称
$1 第一个参数
$n 第n个参数
$# 脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

if

shell 编程中使用到得if语句内常用的判断参数(如果是否的话,在下面的语句前面增加!就行了,注意空格)

  • -eq 等于
  • -ne 不等于
  • -gt 大于
  • -lt 小于
  • -le 小于等于
  • -ge 大于等于
  • -z 空串: if [[ -z "$test" ]]
  • = 两个字符相等
  • != 两个字符不等
  • -n 非空串
  • -e 判断文件是否存在 if [ -e filename ]
  • -d 判断文件件是否存在 if [ -d foldername ]

下面是if elif else fi的语法

if [ "$A" = "GS" ]; then
  echo "yes"
elif [ "$A" = "UC" ]; then
  echo "no"
else
  echo  "your are wrong"
fi

如果if中要有判断条件

# || &&
if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
    echo "Entered $option"
fi

case

casein
模式1)
    command1
    command2
    command3
    ;;
模式2)
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac
  • case后为取值,值后为关键字in,接下来是匹配的各种模式,每一模式最后必须以右括号结束
  • 其中模式支持正则表达式,正则的字符对应如下:
字符 代表的意义
* 任意字串
? 任意字元
[abc] a, b, 或c三字元其中之一
[a-n] 从a到n的任一字元
| 多重选择

变量替换

linux bash shell之变量替换语法: :- - := = :? ? :+ + =?句法,详见Parameter Expansion

  • ${parameter:-word}: Use Default Values. If parameter is unset or null, the expansion of word shall be substituted; otherwise, the value of parameter shall be substituted.(这里使用substituted是因为最后是对表达式的求值)
  • ${parameter:=word}: Assign Default Values. If parameter is unset or null, the expansion of word shall be assigned to parameter. In all cases, the final value of parameter shall be substituted. Only variables, not positional parameters or special parameters, can be assigned in this way.
  • ${parameter:?[word]}: Indicate(提示) Error if Null or Unset. If parameter is unset or null, the expansion of word (or a message indicating it is unset if word is omitted) shall be written to standard error and the shell exits with a non-zero exit status. Otherwise, the value of parameter shall be substituted. An interactive shell need not exit.
  • ${parameter:+word}: Use Alternative Value. If parameter is unset or null, null shall be substituted; otherwise, the expansion of word shall be substituted.
parameter parameter parameter
Set and Not Null Set But Null Unset
${parameter:-word} substitute parameter substitute word substitute word
${parameter-word} substitute parameter substitute null substitute word
${parameter:=word} substitute parameter assign word assign word
${parameter=word} substitute parameter substitute null assign word
${parameter:?word} substitute parameter error, exit error, exit
${parameter?word} substitute parameter substitute null error, exit
${parameter:+word} substitute word substitute null substitute null
${parameter+word} substitute word substitute word substitute null

In all cases shown with "substitute", the expression is replaced with the value shown. In all cases shown with "assign", parameter is assigned that value, which also replaces the expression.

函数

# 没有参数的函数
demoFun() {
    echo "这是我的第一个 shell 函数!"
}
# 调用使用 `demoFun`

# 有返回值 和cli交互的 函数
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
# 调用使用 funWithParam
# 1
# 2
# return 3

# 有参数的函数
funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

端口相关

  • 查看机器全部开放端口
# 查看全部开放端口
nmap <ip>
# 查看某个端口的状态
nmap <ip> -p <port>

操作符相关

shell中的 && || [] {} ()

  • &&: command1 && command2 &&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,"如果这个命令执行成功&&那么执行这个命令",其语法格式如下 command1 && command2 && command3 ...

  • ||: command1 && command2 ||则与&&相反。如果||左边的命令(command1)未执行成功,那么就执行||右边的命令(command2);或者换句话说,"如果这个命令执行失败了||那么就执行这个命令"

  • (): (command1;command2;command3....) 如果希望把几个命令合在一起作为整体执行,shell提供了两种方法。既可以在当前shell也可以在子shell中执行一组命令。一条命令需要独占一个物理行,如果需要将多条命令放在同一行,命令之间使用命令分隔符;分隔。执行的效果等同于多个独立的命令单独执行的效果。eg: ls dir &> /dev/null || (cd /home; ls -lh; echo "success")

  • {}: { command1;command2;command3… } 命令将在子shell而不是当前shell中作为一个整体被执行,只有在{}中所有命令的输出作为一个整体被重定向时

获取命令行参数

How do I parse command line arguments in Bash

# 最简单的方式
while getopts "h?vf:" opt; do
    case "$opt" in
    h|\?)
        show_help
        exit 0
        ;;
    v)  verbose=1
        ;;
    f)  output_file=$OPTARG
        ;;
    esac
done

# 可以自定义的获取数量方式
case $key in
    -e|--extension)
    EXTENSION="$2"
    shift # past argument
    shift # past value
    ;;
    -s|--searchpath)
    SEARCHPATH="$2"
    shift # past argument
    shift # past value
    ;;
    -l|--lib)
    LIBPATH="$2"
    shift # past argument
    shift # past value
    ;;
    --default)
    DEFAULT=YES
    shift # past argument
    ;;
    *)    # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift # past argument
    ;;
esac
done

字符串

获得字符串长度

获得字符串长度

# 在本地完成 不依赖于expr
echo ${#Str}  # s='abcd'; echo ${#s}
# 与 echo ${#Str} 等价 且在大部分平台能运行
echo -n $Str | wc -m
# 通过表达式方式完成
expr length $Str

字符串切割

{string:position:length}

str="abcdefghijklm"
echo "${str:0:5}"
# abcde

判断a字符串是不是b字符串的子串

# 最简单写法,但是不一定判断成功
string='My long string'
if [[ $string = *"My long"* ]]; then
  echo "It's there!"
fi

# 比较法杂的写法,但是可以保证在各个平台中运行
string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
  if [ -z "${string##*$reqsubstr*}" ] ;then
      echo "String '$string' contain substring: '$reqsubstr'."
    else
      echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
  done

列表

# 最简单的列表
for i in 1 2 3; do
    echo "$i"
done
# 变量方式
listVar="1 2 3"
for i in $listVar; do
    echo "$i"
done


## declare an array variable
declare -a arr=("element1" "element2" "element3")
## now loop through the above array
for i in "${arr[@]}"
do
   echo "$i"
   # or do whatever with individual element of the array
done
# You can access them using echo "${arr[0]}", "${arr[1]}" also

文件相关

路径相关

# 获取文件的父目录
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"

命令行写入文件

# 覆盖以后文件内容
echo "cover exists content" > /path/to/file
# 追加到文件后面
echo "cover exists content" >> /path/to/file

# 可能需要写入的文件或文件夹不存在
mkdir -p /path/to/file/
touch /path/to/file/file_name
echo "cover exists content" > /path/to/file/file_name

判断文件夹是否存在

# To check if a directory exists in a shell script you can use the following:
if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

# Or to check if a directory doesn't exist:
if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

判断文件是否存在

if [ -f "$file" ]; then
  # Control will enter here if $file exists.
else
  # Control will enter here if $file doesn't exist.
fi

跟踪日志文件

# 查看文件倒数 100 行
tail -100 fileName.log
# 实时监听文件写入
tail -f file_name.log
# 查看文件的倒数 100 行 并实时监听
tail -100f fileName.log

字符串变量写入文件

将命令行的变量输入到文件中 echo $var > path/to/file 如果变量是string且有换行,echo "$var" > path/to/file。如果有权限的问题,不能执行文件夹里面的文件,可以先新建一个文件夹再创建文件并执行

test="this
is a
test file
"

workdir=/home/ubunt/conf
if [ ! -d $workdir ]; then
mkdir $workdir
touch $workdir/test.tmp
fi

echo "test" > $workdir/test.tmp

查看文件目录树

tree         # 基本文件目录树
tree --help  # 显示tree命令的帮助文档
tree -d      # 只显示文件夹的文件目录树
tree -L 3    # 只显示深度为3的文件目录树

查看文件行数

查看指定文件夹下指定文件的行数how to count all the lines of code in a directory recursively

find ./ -name '*.py' | xargs wc -l

管道

  • 匹配符合内容的项目
ls -a | grep <pattern>
  • 过滤上一个管道的空值
# 如果 /path 路径下没有文件 xargs -I 会过滤掉, 即不会执行 echo "cat %" 命令
ls -1 /path | xargs -I % echo "cat %"
  • 文件夹特定文件是否有符合的模式
# 查看指定文件的内容是否符合
cat <file_name> | grep <pattern>
# 查看一类文件的内容是否符合
ls | grep <pattern_filename> | xargs cat | grep <pattern>
  • 将上一个命令的结果作为参数放在下一个命令| xargs
# 默认会跟在后一个命令的后面 如这里的`cat`命令
ls | xargs cat

# 如果想要在多个地方使用上一结果作为参数 `-I %` eg:git 删除本地和远程的tag
git tag --list 'v1.1.*' | xrags -I % echo 'git tag -d %; git push --delete origin %' | sh
# 启动先 echo 为了防止命令出错

修改相关

  • 修改hosts文件
sudo vim /etc/hosts
# after change file, restart networking
sudo /etc/init.d/networking restart
  • 修改开机启动项

按windwos或者ubuntu键,进入search your computer,搜索startup,add 一个名称是 guake ,位置是 /usr/bin/guake 的应用成簇

  • 修改用户密码
sudo passwd user-name
# enter password and repeat it
  • ubuntu 快捷方式

参照ubuntu添加桌面快捷启动方式的方法。Ubuntu下面所有的快捷方式都放在 /usr/share/applications 下面,当你要创建新的快捷方式的时候,只需要在 /usr/share/applications 创建一个快捷方式名.desktop就行。例如pycharm.desktop。

[Desktop Entry]
Type=Application
Name=Pycharm
GenericName=Pycharm3
Comment=Pycharm3:The Python IDE
Exec="/home/tools/pycharm-2016.1.3/bin/pycharm.sh" %f
Icon=/home/tools/pycharm-2016.1.3/bin/pycharm.png
Terminal=pycharm
Categories=Pycharm;

安装解压运行的软件时,一般是解压出来,确定运行没有问题了, 再将文件夹移动到 /opt 或者 /usr/local 目录 mv download_floder_name /opt/software_name,然后在创建文件的快捷方式

远程

# 远程到默认的 22 端口
ssh user@ip   #  ssh [email protected]

# 远程到非默认端口
ssh user@ip -p port    # ssh [email protected] -p 23

权限相关

  • chmod -x file/folder: 去除执行权限
  • chown mail:mail log2012.log: 改变拥有者和群组
  • chmod 777 -R folder/file: 给文件夹赋权 -R 递归赋权

查看相关

  • du -h --max-depth=1: 查看文件夹的大小,--max-depth选项是文件树的深度
  • du -h <folder_name>: 查看文件夹大小
  • tail -f filename.log: 追踪filename.log日志文件的生成
  • 查看内存用量
    • 单独查看内存使用情况的命令:free -m
    • 查看内存及cpu使用情况的命令:top
    • 也可以安装htop工具,这样更直观
      • 安装命令如下: sudo apt-get install htop
      • 安装完后,直接输入命令:htop
  • 查看默认的shell
  • 查看消耗
    • 查看内存和SWAPfree:操作符-h更友好的显示使用量如MB 或 GB
    • 查看整体消耗情况top,按照CPU消耗排序:在界面上P,按照内存消耗排序:在界面上M
echo $SHELL
  • 查看文件夹中最后修改的两个文件(2 last modified file)ls -lt | head -n 3

进程

  • 杀死进程: kill pid
  • 如果遇到进程kill不死: kill -9 pid

驱动相关

mount /etc/cdrom /media/usb: 挂载磁盘到media/usb目录

拷贝相关

  • 本地文件复制到远程服务器
    • scp local_file remote_username@remote_ip:remote_file
  • 远程服务器复制文件到本地
    • scp remote_username@remote_ip:remote_file local_file
  • -T参数实现两边转换: scp -T local_file remote_username@remote_ip:remote_file是将远程文件复制到本地
  • -r参数实现文件夹复制: scp -r local_folder remote_username@remote_ip:remote_folder,将文件夹复制到远程

时间相关

  • 更改时区、时间

    # 时区
    tzselect   # 然后选择 Asia -> China -> beijing time
    # 时间
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • n天之前或者之后

    # 一天或者n天以前
    date -d '-1 day' '+%Y%m%d'
    
    # 一天或者n天以后
    date -d '+1 day' '+%Y%m%d'

运行相关

  • 运行shell脚本只需要 ./script.sh就行了,但是要有权限chmod u+x script.sh

系统相关

  • 启动系统相关命令
# 重启
sudo reboot
# 关机
sudo shutdown now

安装相关

安装tar.gz程序

  • 解压文件: tar -zxvf filename.tar.gz或者到指定的目录中tar -zxvf filename.tar.gz -C /path/to/folder
  • 进入目录执行配置命令: ./configure或者指定安装路径./configure --prefix=/path/to
  • 进行软件编译: make
  • 完成安装: make install
  • 清除安装临时文件: make clean

安装AppImage文件

关于AppImage文件

AppImages can be downloaded and run without installation or the need for root rights.

# Making it executable
chmod a+x exampleName.AppImage
# Executing it
./exampleName.AppImage

安装deb软件包

  • 双击运行
  • sudo dpkg -i package-name.deb

卸载软件

  • 如果是从Ubuntu Software Center安装的,进入center,找到那个软件,很明显会有remove的按钮

  • 如果是targzzip之类解压就能用,免安装的,直接删除

  • 如果是自己下载的deb包安装,或者通过apt-get install安装、或者通过添加ppa安装,使用sudo apt-get autoremove software-name来卸载,为了一次卸干净,可以再加上一个参数sudo apt-get autoremove --purge software-name

  • 如果是通过configure然后make & make install,也可以直接删除;

  • apt install 或者 apt update 提示No space left on device,df -h查看机器容量时发现/boot盘满了,可以自动卸载sudo apt autoremove让软件管理器自动卸载过期的程序

  • PPA源相关: 部分软件是个人的源,安装的时候要增加ppa源sudo add-apt-repository ppa:<ppa-repository>,然后运行sudo apt-get update; sudo apt-get install <soft>就能安装相应的软件了.添加的第三方PPA源的位置在/etc/apt/sources.list.d/*,内置的源的位置在/etc/apt/sources.list, 如果想要卸载第三方的源,运行sudo add-apt-repository --remove ppa:<ppa-repository>,然后在/etc/apt/sources.list.d/*目录中删除相应的list和save

快捷键

长按 super: 打开启动器 显示快捷键

super + [1-9]数字: 快速启动状态栏上指定位置的应用

ctrl + super + D: 最小化所有窗口 ctrl + super + up: 最大化窗口 ctrl + super + down: 最小化窗口

alt + F4: 关闭当前窗口

alt + tab: 切换不用应用 alt + \``: 同一应用(多开)切换另一个独立窗口 alt + tab`: 同一应用(单开)切换另一个窗口 ``

错误处理

# 方法一 重启搜狗输入法
killall fcitx
killall sogou-qimpanel

# 方法二 修复安装依赖 看是否缺失
sudo apt-get install -f

# 方法三 删除配置文件 重启搜狗 关闭输入法进程
cd ~/.config
rm -rf SogouPY/ SogouPY.users/ sogou-qimpanel/
# 最后销重新登录
  • 开启了 22 端口,但是 ssh 一直失败
# ufw 已经看到 22 端口开了
sudo ufw status
# 检查本机的所有端口 发现22 端口没有开启
sudo nmap 127.0.0.1

why cant i allow access to port 22发现要安装 openssh-server,原来ubuntu默认只是装了ssh 客户端,没有默认安装服务端

  • shadowsocks-qt5 failed to connect server

在新装了一台ubuntu,使用的是 shadowsocks-qt5 本来ss客户端是能链接上google的,但是安装完了软件之后就发现不能连接了。我在自己的手机和windows都能上网,用windows机器google了一下,发现了有人遇到相同的问题,于是看了下端口netstat -nlp | grep 1080,发现应该是迅雷占用了1080端口,于是将ss客户端端口进行修改,就能正常的科学上网了

图形化操作相关

  • 文件夹显示的方式

ctrl + F1 采用list方式显示文件, ctrl + F2 采用 icons方式显示文件,也可以用过view -> list or icons进行切换

  • 显示隐藏文件

ctrl + H切换是否显示隐藏文件,或者通过view -> show hidden files进行过切换

计算信息摘要

  • MD5: md5sum file_name
  • SHA1: sha15sum file_name

设置命令行工具

  • 为了防止rm带来的悲剧

    • 模拟一个回收站
    # 家目录创建一个回收站文件夹
    mkdir ~/.trash
    
    # 创建一个 remove.sh 脚本
    vim ~/tool/remove.sh
    # 定义 .trash 文件夹
    TRASH_DIR="/home/user/.trash"
    for i in $*; do
      # 定义秒的时间戳
      STAMP=`date+%s`
      # 得到文件夹名称
      fileName=`basename $i`
      # 移动到 ~/.tarsh 文件夹
      mv $i $TRASH_DIR/$fileName.$STAMP
      # 创建一个提醒
      echo "run remove.sh move $i to $TRASH_DIR/$fileName.$STAMP"
    done
    
    # 修改 .bashrc 增加一行 设置一个 rm 同名的 alias
    vim ~/.bashrc
    alias rm="sh /home/user/tool/remove.sh"
    
    # 设置定时任务定时删除自定义的回收站 crontab
    0 0 * * 0 rm -rf /home/user/.trash/*
    
    # 改进的地方 {设置回收站的最大容量,当单个文件夹大于回收站的最大容量后直接删除文件.当到了文件积累到最大容量后删除最久的文件}
    • 鸟哥私房菜给 rm 起一个别名

制作u盘启动盘

# 查看u盘挂载在哪里
sudo fdisk -l
# 运行写入命令
sudo dd if=/path/to/iso of=/path/to/dev

FAQ

怎么运行sh文件

How do I run .sh files

chmod +x /path/to/yourscript.sh
/path/to/yourscript.sh
# 如果你的脚本在当前目录
./yourscript.sh

su 切换用户且运行多行命令

Running multiple commands with su in Bash

# 更多查看 su --help
su hive -c "run command here"

bash中进行运算

count=$((FIRSTV-SECONDV))
count=$(expr $FIRSTV - $SECONDV)

遍历管道来的变量

有时候需要对管道过来的变量进行更多的处理,可以使用while read f处理

hdfs dfs -ls /path/to/hdfs | while read f; do
    dsField=$(echo $f | cut -d "/" -f 7)
    if [ ! -z $dsField ] && [ $(expr length $dsField) -gt 11 ]; then
        echo "hdfs dfs -rm -r -skipTrash $f"
    fi
done

读取配置文件中的数据

Read values from configuration file and use in shell script

# cat config.sh
[email protected]
user=test
password=test

# command line
source $<your_file_path>
echo $email

查看内存总数和cpu核数

# cpu 核数
grep -c ^processor /proc/cpuinfo
# 内存总数
free -g

修改echo的颜色输出并加提示

# color hint echo
checho() {
    # color
    RED="\033[0;31m"
    GREEN="\033[0;32m"
    YELLOW="\033[1;33m"
    # ... ADD MORE COLORS
    NC="\033[0m"   # No Color

    # hint
    BIG="====>"
    SMALL="  -->"

    printf "${!1}${!2} ${3} ${NC}\n"
}

获取当前运行文件的全路径

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

判断命令行是否执行正确

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

判断是否是子字符串

string='My long string'
if [[ $string == *"My long"* ]]; then
  echo "It's there!"
fi

将'/'替换成'/'

需要将变量中的'/'替换成'/',详见这里

input="a/b/c/d"
echo "${input//\//\\/}"
a\/b\/c\/d

⚠️ **GitHub.com Fallback** ⚠️