easyBCD=>Add New Entry=>NeoGrub=>Install=>Configure
title Install Ubuntu
root (hd0,0)
kernel (hd0,0)/vmlinuz.efi boot=casper iso-scan/filename=/ubuntu.iso ro quiet splash locale=zh_CN.UTF-8
initrd (hd0,0)/initrd.lz
把ubuntu.iso放到C盘,并解压其中的vmlinuz.efi及initrd.lz也放到C盘
如果启动后显示File not found,可以试试把ISO文件名改短,或者把vmlinuz.efi改成vmlinuz,或者检查一下C盘是不是(hd0,0)
安装前要卸载挂载点
sudo umount -l /isodevice
ubuntu
22.04及以下版本换源,22.04的代号是jammy
,其他版本自行替换:
# 先备份原来的源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
# 修改源
sudo gedit /etc/apt/sources.list
# 把阿里云的源复制进去
deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
# deb http://mirrors.aliyun.com/ubuntu/ jammy-proposed main restricted universe multiverse
# deb-src http://mirrors.aliyun.com/ubuntu/ jammy-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
ubuntu
24.04版本换源,24.04的代号是noble
,其他版本自行替换:
# 先备份原来的源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
# 修改源
sudo gedit /etc/apt/sources.list
# 把官方的源注释掉,再把清华的源复制进去
Types: deb
URIs: http://mirrors.tuna.tsinghua.edu.cn/ubuntu/
Suites: noble noble-updates noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
sudo apt-get remove libreoffice-common gnome-sudoku aisleriot gnome-mahjongg gnome-mines deja-dup
更新
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo update-manager -c -d
do-release-upgrade
驱动安装
ubuntu-drivers devices
sudo ubuntu-drivers autoinstall
如果安装软件时提示缺失依赖,执行以下命令修复
sudo apt install -f
gedit
sudo apt install gedit
压缩工具
sudo apt install unzip
sudo apt-get install unrar
sudo apt-get install p7zip-full
图形化压缩软件
sudo apt install xarchiver
下载工具
apt-get install axel
sudo add-apt-repository ppa:t-tujikawa/ppa
sudo apt-get update
sudo apt-get install aria2
sudo gedit /usr/local/bin/Aria2c
# (粘贴)
aria2c --enable-rpc --rpc-listen-all --rpc-allow-origin-all --file-allocation=none --max-connection-per-server=3 --max-concurrent-downloads=5 --continue -d ~/Downloads/
sudo chmod +x /usr/local/bin/Aria2c
zsh
sudo apt-get install zsh
# 下载 oh-my-zsh 项目来帮我们配置 zsh
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
# 或
git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
chsh -s /bin/zsh
新建文件XXX.desktop
,内容如下
[Desktop Entry]
Version=1.0
Type=Application
Name=XXX
Icon=/usr/local/xxx.png
Exec=/usr/local/xxx
Comment=XXX
Categories=TextEditor;Development;Math;Science
Terminal=false
StartupNotify=true
MimeType=text/markdown;text/x-matlab
最后sudo mv XXX.desktop /usr/share/applications
或者mv /home/xxx/.local/share/applications
Albert Spotlight
sudo add-apt-repository ppa:noobslab/macbuntu
sudo apt-get update
sudo apt-get install albert
gnome-tweak-tool
sudo apt-get install gnome-tweak-tool
# 或者
sudo apt install gnome-tweaks
#Ubuntu可能已经自带gnome-shell
sudo apt-get install gnome-shell
sudo apt-get install chrome-gnome-shell
安装gnome插件
推荐的插件:TopIcons Plus、NetSpeed、Dash to Dock (https://micheleg.github.io/dash-to-dock/download.html)
部分插件可以解压后直接放到~/.local/share/gnome-shell/extensions/
下,然后按Alt+F2 r Enter
重启gnome生效,如果没有生效,可以通过dconf
把文件夹名加到/org/gnome/shell/enabled-extensions
的key中
安装gnome主题
推荐的主题:McMojave、T4G-Shell-theme III
推荐的图标:Reversal icon theme、Mojave CT icons
安装gnome-shell
主题前要先安装User
Themes插件,或者把主题放到/usr/share/themes
,图标放到/usr/share/icons
更改Grub主题
,推荐Grub-theme-vimix
安装Grub主题前要先安装Grub2
sudo apt-get install grub2
# 安装默认主题
sudo apt-get install grub2-themes-ubuntu-mate
# 下载主题,将主题文件夹者复制到 /boot/grub/themes/
# 然后执行(文件夹也有可能是/etc/default/grub2)
sudo gedit /etc/default/grub
# 找到GRUB_THEME,改为
GRUB_THEME=/boot/grub/themes/my-theme/theme.txt
# 再把GRUB_HIDDEN_TIMEOUT=0注释掉
# 更新grub
sudo update-grub
# 没有update-grub命令的可以执行
sudo grub-mkconfig -o /boot/grub/grub.cfg
安装Plymouth开机动画,推荐Ubunut Spinner Logo Plymouth
# 把开机动画放到plymouth目录下
sudo mv ./my-theme /usr/share/plymouth/themes/
# 修改默认开机动画
sudo ln -sf /usr/share/plymouth/themes/my-theme/my-theme.plymouth /etc/alternatives/default.plymouth
# 或者用update-alternatives安装
sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/mytheme/mytheme.plymouth 100
# 选择要用的开机动画
sudo update-alternatives --config default.plymouth
# 更新内核
sudo update-initramfs -u
修改启动页背景(Ubuntu18.04及以前)
sudo cp pic.png /usr/share/backgrounds/
# 修改
sudo gedit /etc/alternatives/gdm3.css
把
#lockDialogGroup {
background: #2c001e url(resource:///org/gnome/shell/theme/noise-texture.png);
background-repeat: repeat; }
改为
#lockDialogGroup {
background: #2c001e url(file:///usr/share/backgrounds/pic.png);
background-repeat: no-repeat;
background-size: cover;
background-position: center; }
Ubuntu20.04的更改方法
https://github.com/thiggy01/change-gdm-background
#添加执行权限
sudo chmod 777 change-gdm-background
#运行脚本,设置壁纸路径(/path/to/image)
sudo ./change-gdm-background /path/to/image
或者 https://github.com/PRATAP-KUMAR/ubuntu-gdm-set-background
# 安装依赖
sudo apt install libglib2.0-dev-bin -y
#运行脚本
sudo ubuntu-gdm-set-background --image /path/to/image
Ubuntu22.04及以上的更改方法
22.04及以上需使用gnome插件,且卸载插件后效果会消失: https://github.com/PRATAP-KUMAR/gdm-extension
方法1:通过apt安装
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update && sudo apt-get install oracle-java9-installer
方法2:建立符号链接(通过update-alternatives --install link name path priority
命令,删除就update-alternatives --remove name path
)
下载JDK压缩包(Oracle JDK、OpenJDK),解压并复制到/usr/lib/jvm后,然后执行
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-22.0.2/bin/java 300
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk-22.0.2/bin/javac 300
sudo update-alternatives --install /usr/bin/jar jar /usr/lib/jvm/jdk-22.0.2/bin/jar 300
sudo update-alternatives --install /usr/bin/javap javap /usr/lib/jvm/jdk-22.0.2/bin/javap 300
# 设置默认jdk
sudo update-alternatives --config java
方法3:添加环境变量
sudo mkdir /usr/local/java
# 解压并复制jdk进去
mkdir ./jdk-22.0.2
tar -xzvf openjdk-22.0.2_linux-x64_bin.tar.gz ./jdk-22.0.2
sudo cp -a ./jdk /usr/local/java/
sudo gedit /etc/profile
# 在最后加上
JAVA_HOME=/usr/local/java/jdk-22.0.2
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH
# 重启后生效,或者输入以下命令在当前命令行生效
source /etc/profile
方法一:通过apt安装
sudo apt install nodejs
# 查看node、npm版本确认是否安装成功
node -v
npm -v
方法二:建立软链接
下载安装包,解压,然后执行
mkdir -p /opt/node/
mv ./node-v20.9.0-linux-x64.tar.gz/* /opt/node/
# 如果之前已经建立了软链接,则先删掉
rm -f /usr/local/bin/node
rm -f /usr/local/bin/npm
# 然后建立软链接
ln -s /opt/node/bin/node /usr/local/bin/node
ln -s /opt/node/bin/npm /usr/local/bin/npm
换源
# 查看当前的源,没改过就应该是官方源 https://registry.npmjs.org/
npm config get registry
# 临时换源,每条命令都要加 --registry <URL>
npm --registry <URL> install xxx
# 永久换源,要恢复就改回官方的URL
npm config set registry <URL>
# 也可以使用nrm来管理源
npm i -g nrm
# 列出所有可用的源
nrm ls
# 使用指定的源
nrm use <source_name>
# 自定义源名称和地址
nrm add <source_name> <URL>
# 删除自定义源
nrm del <source_name>
# 测试速度
nrm test <source_name>
更新Node.js和npm的版本
# 通过版本管理工具n升级,这样会同时更新Node.js和npm
sudo npm install n -g
# 查看是否安装成功
n -V
# n的命令如下
sudo n 20.9.0 #升级到指定版本
sudo n latest #升级到最新版本
sudo n lts #升级到长期支持版本
sudo n stable #升级到最新的稳定版本
# 也可以只升级npm
sudo npm install npm -g
清除缓存、模块等常用命令
# 清除npm缓存
npm cache clean -f
# 列出所有全局顶级模块
npm ls -gp --depth=0
# 清除所有全局模块(列出所有顶级模块后,排除以“/npm”结尾的npm本身的所有模块,然后执行删除)
npm ls -gp --depth=0 | awk -F/ '/node_modules/ && !/\/npm$/ {print $NF}' | sudo xargs npm -g rm
Linux编译安装指定版本的Python
# 解压
sudo tar -zxvf Python-3.10.11.tgz -C .\
cd Python-3.10.11# 通过"--prefix="指定python安装的位置
./configure --prefix=/usr/local/python3.10.11
# 编译安装
sudo make
sudo make test
sudo make install
# 如果报错,可能是编译环境没配好,尝试安装以下依赖
sudo apt-get install zlib1g-dev libbz2-dev libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libpcap-dev xz-utils libexpat1-dev liblzma-dev libffi-dev libc6-dev
# 更新python默认指向
# 方法一
# 先查看目前系统默认的python
ls -l /usr/bin | grep python
# 手动建立python符号链接
sudo mv /usr/bin/python /usr/bin/python.bak
sudo mv /usr/bin/python3 /usr/bin/python3.bak
sudo ln -s /usr/local/python3.10.11/bin/python3.10 /usr/bin/python
sudo ln -s /usr/local/python3.10.11/bin/python3.10 /usr/bin/python3
# 手动建立pip符号链接
sudo mv /usr/bin/pip /usr/bin/pip.bak
sudo mv /usr/bin/pip3 /usr/bin/pip3.bak
sudo ln -s /usr/local/python3.10.11/bin/pip3 /usr/bin/pip
sudo ln -s /usr/local/python3.10.11/bin/pip3 /usr/bin/pip3
# 方法二
# 先查看系统目前已配置的可用python版本
sudo update-alternatives --list python
# 先为各版本创建符号链接(未安装的版本跳过),这里假设python安装在默认位置
# (在自动模式下,最后的数字越大,优先级越高,不过我们这里会指定默认python版本,所以数字无所谓)
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.10 2
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.11 3
# pip同理,不过pip一般使用最高版本就可以兼容大部分情况
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.10 300
sudo update-alternatives --install /usr/bin/pip3 pip3 /usr/bin/pip3.10 300
# 选择默认指向
sudo update-alternatives --config python
# 对于不再使用的版本,可以移除
update-alternatives --remove python /usr/bin/python2.7
pip2和pip3
sudo apt-get install python-pip python-dev build-essential
sudo pip install --upgrade pip
sudo apt-get install python3-pip
sudo pip3 install --upgrade pip
# 或者使用python自带的工具安装pip
python -m ensurepip --upgrade
便携版python安装(Windows)
下载embeddable版的python,该版本是便携版,不带pip,所以还要安装pip:
1、解压后进入python目录,检查python版本python --version
2、安装pip(参考):
curl -L https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
3、便携版的python需找到python3x._pth
(x是版本号),把import site
前面的#
删掉,才能自动识别pip
4、如果pip还是不能运行,在python3x._pth
最后加上一行Lib/site-packages
注意:便携版的python在使用pip的时候最好不要直接使用pip
,而是使用python -m pip
调用。
注意:如果后续移动了python文件夹的位置,python\Scripts
目录下的可执行文件无法直接使用,需要指定python.exe
,比如".\python\python.exe" ".\python\Scripts\libretranslate.exe" --host 127.0.0.1 --port 5000
.
常用命令
# pip临时换源,每条命令都要加 -i <URL>
python -m pip install <module_name> -i <URL>
# pip永久换源,并删除缓存
python -m pip config set global.index-url <URL>
python -m pip cache purge
# 换回默认源
python -m pip config unset global.index-url
# 一些源的地址
# https://mirrors.aliyun.com/pypi/simple/
# https://pypi.mirrors.ustc.edu.cn/simple/
# 如果换源后警告,添加信任即可
python -m pip install <module_name> --trusted-host pypi.tuna.tsinghua.edu.cn
# pip更新
python -m pip install --upgrade pip
# 安装模块
python -m pip install <module_name>
# 也可以用源码安装,即包含setup.py的文件夹或者tar.gz压缩包
python -m pip install "/path/to/project_folder"
# 更新模块
python -m pip install --upgrade <module_name>
# 更新所有模块
python -m pip install pip-review
python -m pip-review --local --interactive
# 列出已安装的模块
python -m pip list
# 卸载模块
python -m pip uninstall <module_name>
# 安装虚拟环境模块,默认python3是内置venv的,便携版python3或python2则需安装virtualenv模块,对应的创建环境命令也需更改
python -m pip install --upgrade virtualenv
# 创建虚拟环境,使得项目使用的模块可以单独存在,不影响全局的模块
# 默认虚拟环境中的模块都需要显式安装才可用,如果想在该虚拟环境中使用系统已安装的模块则需指定--system-site-packages
# 该命令会创建DIRECTORY目录,并生成pyvenv.cfg文件、Lib及Scripts文件夹(Linux下为bin文件夹),里面包含符号链接
python -m venv <path/to/DIRECTORY>
python -m virtualenv <path/to/DIRECTORY>
# Windows激活虚拟环境
.\DIRECTORY\Scripts\activate
# Linux激活虚拟环境
source ./DIRECTORY/bin/activate
# 取消激活虚拟环境
deactivate
# 要删除虚拟环境则删除整个目录即可
rm -rf DIRECTORY
# 导出项目所需模块列表
python -m pip freeze > requirements.txt
# 一键安装项目所需的模块,一般目录下会有一个requirements.txt文件
python -m pip install -r requirements.txt
# 检查模块是否已经安装
python -m pip check -r requirements.txt
# 一键卸载第三方模块,原理是先导出requirements.txt,再根据requirements.txt卸载,不过会把pip也卸载掉,需重新安装pip
python -m pip uninstall -r requirements.txt -y
在联网环境下下载whl
文件,以便离线安装模块:
# 下载whl文件,platform一般是linux_x86_64、win_amd64、macosx_10_9_x86_64等
python -m pip download <package_name> --only-binary=:all: --wheel --platform <platform> --python-version <python_version>
# 比如
python -m pip download numpy --only-binary=:all: --wheel --platform win_amd64 --python-version 311
# 离线环境安装whl,需指定禁止查询在线索引(--no-index)以及在当前目录下查找whl文件进行安装(--find-links)
python -m pip install --no-index --find-links="/path/to/packages" <package_name.whl>
# 根据requestments.txt批量下载whl到文件夹,默认只会下载当前platform下的包,且如果安装环境下的pip版本过低可能会报错
python -m pip download -r requestments.txt -d ./pip_packages
# 离线安装requestments.txt中的包
python -m pip install --no-index --find-links=./pip_packages -r requirements.txt
LAMP
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install apache2
systemctl status apache2 # 检查apache2是否启动
/etc/init.d/apache2 start
/etc/init.d/apache2 stop
/etc/init.d/apache2 restart
sudo apt-get install mysql-server mysql-client libmysqlclient-dev
sudo netstat -tap | grep mysql # 检查mysql是否安装成功
sudo gedit /etc/mysql/debian.cnf # 查看mysql默认用户名密码
mysql -u debian-sys-maint -p # 登录mysql
update mysql.user set authentication_string=password('password') where user='debian-sys-maint'and Host = 'localhost'; # 更改密码
update mysql.user set user="user" where user="debian-sys-maint"; # 更改用户名
flush privileges; # 刷新权限
sudo apt-get install mariadb-server-10.0 mariadb-client-10.0
sudo mysql_secure_installation # 配置Mariadb
sudo apt-get install php7.2
sudo apt-get install php7.2-mysql libapache2-mod-php7.2 php7.2-curl php7.2-json php7.2-cgi
sudo service mysql restart
sudo service apache2 restart
sudo apt-get install curl ruby
禁用guest
sudo gedit /usr/share/lightdm/lightdm.conf.d/50-no-guest.conf
# (粘贴)
[SeatDefaults]
allow-guest=false
关闭错误报告
sudo rm /var/crash/*
sudo gedit /etc/default/apport
调节亮度
sudo gedit /sys/class/backlight/intel_backlight/brightness
CA证书安装位置:/usr/local/share/ca-certificates/
使用flatpak应用框架: https://flatpak.org/setup/Ubuntu、https://flathub.org
firefox: https://support.mozilla.org/en-US/kb/install-firefox-linux
Chrome: https://www.google.cn/intl/en_uk/chrome/
sougou输入法: http://pinyin.sogou.com/linux/
# 装完再安装依赖
sudo apt install -f
# 若无法显示界面,尝试安装以下依赖
sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2
sudo apt install libgsettings-qt1
# 若还是不能运行,尝试卸载ibus
sudo apt purge ibus
sudo apt-get install wps-office
解决字体缺失、在Ubuntu22.04上无法打开等问题
# 解决字体缺失
# 先下载字体文件wps-symbol-fonts.zip,解压到/usr/share/fonts/wps-office/或/home/xxx/.local/share/fonts/wps-office
sudo mkfontscale
sudo mkfontdir
sudo fc-cache
# 解决在Ubuntu22.04上无法打开
# 给WPS的安装目录设置777的权限
sudo chmod 0777 -R /opt/kingsoft/wps-office
# 删除之前WPS的安装设置
rm -rf ~/.config/Kingsoft/
VLC: http://www.videolan.org
sudo snap install vlc
Haroopad: http://pad.haroopress.com/user.html
VSCode: https://code.visualstudio.com/
GIMP
sudo apt-get install gimp
shutter
sudo add-apt-repository ppa:shutter/ppa
sudo apt-get update && sudo apt-get install shutter
octave
sudo apt-get install octave
BleachBit: http://www.bleachbit.org/download/linux
VirtualBox: https://www.virtualbox.org
sudo apt install virtualbox virtualbox-ext-pack virtualbox-guest-additions-iso
Veracrypt: https://www.veracrypt.fr/en/Downloads.html
# 若不能运行,尝试安装libfuse2
sudo apt install libfuse2
AndroidStudio: https://developer.android.google.cn/studio
Genymotion: https://www.genymotion.com
jMonkeyEngine: https://github.com/jMonkeyEngine/jmonkeyengine
Wudao-dict: https://github.com/ChestnutHeng/Wudao-dict
indicator-sysmonitor: https://github.com/fossfreedom/indicator-sysmonitor
Katoolin: https://github.com/LionSec/katoolin
FileZilla: https://filezilla-project.org
Wine: https://wiki.winehq.org/Ubuntu
Pandoc: http://pandoc.org/installing.html#linux
FFmpeg: https://ffmpeg.org/download.html
Mathematica: http://www.wolfram.com/mathematica/
Netease Cloud Music: http://music.163.com/#/download
命令行环境变量设置
# 查看当前环境变量
printenv
# 或者
env
# 临时设置环境变量
export VARIABLE_NAME="value"
# 临时追加环境变量,以PATH为例
export PATH="$PATH:/new/directory/path"
# 为当前用户永久设置环境变量,一般会根据不同系统把环境变量放在.bashrc、.profile或.bash_profile文件中
echo 'export VARIABLE_NAME="value"' >> ~/.bashrc
source ~/.bashrc
# 同理,对所有用户,环境变量一般放在/etc/profile或/etc/environment文件中
sudo echo 'export VARIABLE_NAME="value"' >> /etc/profile
解决ubuntu与windows的时差
timedatectl set-local-rtc 1 --adjust-system-clock
sudo hwclock --localtime --systohc
用户组管理,以安装Android Studio硬件加速(KVM)为例
# 检测是否支持kvm
kvm-ok
# 安装kvm
sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
# 将当前用户添加到KVM组和libvirtd组
sudo adduser myusername kvm
sudo adduser myusername libvirt-qemu
# 卸载
# 查看用户/用户组
sudo cat /etc/shadow
sudo cat /etc/group
# 如果要把用户从用户组中移除
sudo gpasswd -d myusername kvm
sudo gpasswd -d myusername libvirt-qemu
# 删除用户组
sudo groupdel kvm
sudo groupdel libvirt-qemu
修复Ubuntu无法访问Windows磁盘分区
sudo apt-get install ntfs-3g
让gedit显示GB2312
sudo apt-get install dconf-tools
dconf-editor
# 依次点开->org->gnome->gedit->preferences->encodings,把Custom value改成
# ['UTF-8', 'GB18030', 'GB2312', 'GBK', 'BIG5', 'CURRENT', 'UTF-16']
解压/压缩命令
7z x file file
tar -jxvf file.tar.bz2
tar -zxvf file.tar
7za a -t7z -r test.7z ~/tozip/*
tar zcvf test.tar.gz ~/tozip/*
tar jcvf test.tar.bz2 ~/tozip/*
unzip -O cp936 test.zip # 解决乱码问题
清理内核
uname -a
sudo dpkg --get-selections |grep linux
sudo apt-get purge linux-headers-x.x.x-xx linux-image-x.x.x-xx-generic
sudo update-grub
修复引导
sudo -i
add-apt-repository ppa:yannubuntu/boot-repair
apt-get update
apt-get install -y boot-repair
boot-repair
用grep
查找字符串
# 在当前目录下的所有文件的内容中查找字符串str(其中 -r 是递归查找, -n 是显示行号)
grep -rn "str" ./
# 查找文件名包含指定字符串
find . -name 'str'
# 也可以结合起来用
find ./ -name "*.*" | xargs grep "Hello"
# 或者(其中 -l 表示只显示文件名)
find . | xargs grep -ri "Hello" -l
# 如果不知道文件所在的大致目录,只知道文件的类型(比如.txt),可以在根目录(/)下查找
find / -type f -name "*.txt" | xargs grep "Hello"
查看、清理进程
ps -aux | grep XXX
kill -9 PID
网卡开启monitor模式
iwconfig
iwconfig wlan0 mode monitor
airodump-ng wlan0
iwconfig
airmon-ng start wlan0
iwconfig
airodump-ng mon0
airodump-ng -d BSSID_address --channel 11 -w outputfile mon0
airmon-ng stop wlan0
安装win10以上的系统时,强制要求联网并登录账号,在联网界面,可以按Shift+F10调出命令行,然后执行oobe\bypassnro
,重启后会出现没有网络的选项。
Windows
Defender保护历史记录路径在C:\ProgramData\Microsoft\Windows Defender\Scans\History\Service\DetectionHistory
,删除该文件夹下的所有文件即可删除记录。
diskpart命令:想要知道分卷的编号,先用cmd执行diskpart
进入新的命令行窗口,然后执行:
# 列出所选磁盘的分卷
list diskselect disk n # n为要选择的磁盘编号
list partition
# 或者显示所有分卷,但是有的隐藏分卷不会被列出来(随便选择一个磁盘后才能使用)
list volume
# 还可以给分卷分配盘符
select partition n # n为要选择的分卷编号
=D assign letter
bcdedit命令:
# 列出所有的BCD启动项
/enum # 或者不指定参数,直接使用bcdedit也可以列出
bcdedit # 设置默认引导项
/default {identifier}
bcdedit # 设置超时时间(单位为秒)
/timeout 10
bcdedit # 创建引导项,一般会在创建时用“/d”指定描述
/create /d "new_system"
bcdedit # 更改引导项的参数,比如描述(即菜单上显示的名字)、磁盘分卷等
/set {identifier} description "new description"
bcdedit /set {identifier} osdevice partition=\Device\HarddiskVolume2
bcdedit # 用Grub引导Windows,其中"{bootmgr}"是Boot Manager的标识符
#({bootmgr}中Windows默认的引导路径是 \EFI\Microsoft\Boot\bootmgfw.efi,Ubuntu默认的引导路径是 \EFI\ubuntu\grubx64.efi)
#(BCD菜单中默认Windows的引导路径是\Windows\system32\winload.efi)
/set {bootmgr} path \EFI\ubuntu\grubx64.efi
bcdedit /set {identifier} path \Windows\system32\winload.efi
bcdedit # 更简单的创建方法是复制现有的配置再更改,其中“{current}”是指当前系统的引导项
/copy {current} /d "new_system"
bcdedit # 用“/create”创建的引导项不会出现在BCD菜单中,需通过“/displayorder”指定顺序才会显示
/displayorder {identifier1} {identifier2} ...
bcdedit # 在最后面添加引导项
/displayorder {identifier} /addlast
bcdedit # 删除引导项
/delete {identifier}
bcdedit # 备份BCD
/export c:\bcdbak
bcdedit # 恢复BCD
/import c:\bcdbak
bcdedit # 禁用驱动签名,有时候驱动有问题无法开机可以试试
/set nointegritychecks on bcdedit
注意:bcdedit无法识别不同硬盘,只能识别不同分卷,要引导另一个硬盘上的分卷,就根据disk0、disk1等,按顺序执行diskpart
的list partition
命令,然后顺延volume编号,得到\Device\HarddiskVolume
的号码,再设置osdevice partition=xxx
;比如disk0有两个volume,disk1中第一个volume是另一个系统,那么就是\Device\HarddiskVolume3
,依此类推。
bcdboot命令:
:
Ccd C:\Windows\System32
:\Windows /addlast /s D: bcdboot C
命令参数解析:
bcdboot C:\Windows
:
BCDBoot使用%WINDIR%\System32\Config\BCD-Template
文件创建新的启动项,该参数指定在复制启动环境时用作源的Windows目录的位置;在双Windows系统中,若另一个系统没有被列出来或无法进入,比如D盘中的系统,在启动菜单中按Shift+F10
进入命令行,然后输入bcdboot D:\Windows
命令即可修复;/addlast
:将新建的启动项添加到启动顺序列表的底部,默认是添加到顶部;/s <volume letter>
:指定系统分区的卷号,配置要在另一台计算机上启动的驱动器(例如U盘或移动硬盘),需使用此设置来指定系统分区,平时的正常安装不要使用该选项;/m
:如果该Windows分区已有一个启动项,默认会删除旧的启动项及其值,可以使用/m
来将现有启动项中的值合并到新的启动项中;修改cmd默认编码为UTF-8
# 查看当前默认编码,936为GBK,65001为UTF-8
chcp# 临时修改为UTF-8
65001
chcp
# 永久修改则需改注册表,注册表找到如下路径
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor# 然后选中Command Processor,右键新建字符串,命名为autorun,值填入chcp 65001>nul
命令行设置环境变量
# 查看所有环境变量
set
# 查看比如以pa开头的环境变量
set pa
# 临时修改或追加环境变量,值为""表示清空该环境变量
set "VARIABLE_NAME"="value"
set "path"="%path%;xxx;"
# 永久修改或追加环境变量,不加/m修改的是当前用户环境变量,加/m表示修改系统环境变量
"VARIABLE_NAME" "value"
setx "VARIABLE_NAME" "%VARIABLE_NAME%;value;"
setx "VARIABLE_NAME" "value" /m
setx "VARIABLE_NAME" "%VARIABLE_NAME%;value;" /m setx
清除powershell记录
Remove-Item (Get-PSReadlineOption).HistorySavePath
管理员权限相关
# 检查当前是否以管理员权限运行,核心思想就是试图访问需要管理员身份才可以访问的资源,无权访问结果为0
"HKU\S-1-5-19"
REG QUERY
# 申请管理员权限
# VBS方式
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit
cd /d "%~dp0"
# powershell方式,其中%~sdpnx0指当前批处理文件
-Command "Start-Process '%~sdpnx0' -Verb RunAs"&&exit
powershell
# 结合使用
"HKU\S-1-5-19">NUL 2>&1 || (powershell -Command "Start-Process '%~sdpnx0' -Verb RunAs"&&EXIT)
REG QUERY
# 将当前目录下的run.exe注册为需要使用管理员运行的程序,这样以后打开run.exe都会弹UAC框
"HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" /f /v "%~dp0\run.exe" /d "~ RUNASADMIN" >NUL 2>NUL
reg add
# 让需要管理员权限的软件以普通权限运行,原理是通过设置环境变量来使用兼容层运行
/min /C "set __COMPAT_LAYER=RUNASINVOKER && start "" "C:\my programs\file.exe ""
cmd # 或者使用时把软件拖到cmd文件的图标上
/min /C "set __COMPAT_LAYER=RUNASINVOKER && start "" %1" "" cmd
其他常用命令:
# 遍历目录,并执行命令,比如递归遍历当前目录下所有jpg并复制到指定文件夹
/p . /m *.jpg /s /c "cmd /c copy @path D:\photos"
forfiles # 获取帮助
/?
forfiles
# 在指定的文件中查找字符串
"str" test.txt
findstr # 在当前目录下的所有文件里查找字符串(其中/s表示包含子目录,/n表示显示行号,/i表示忽略大小写)
/s /n /i "str" *.*
findstr
# 比较两个文件
fc file1.txt file2.txt
# 获取帮助
fc /?
# windows下创建任意大小空白文件,比如1G,即1024*1024*1024*1
1.txt 1073741824
fsutil file createnew
# 合并文件(比如ts)
copy /b .\*.ts .\new.ts
# 得到文件的MD5
-hashfile filename MD5
certutil
# 证书管理器
.msc
certmgr
# MSConfig
msconfig
# 将文件夹映射成虚拟磁盘
: C:\Downloads
subst A# 不带参数即查看映射
subst# 删除映射
: /D
subst A
# Bitlocker回锁
-lock D:
manage-bde
# 查看当前的文件类型关联(cmd输入,不指定类型则查看所有)
.mp4
assoc # 指定打开方式(等号后面为空就是删除关联的打开程序的意思)
.mp4=WMP11.AssocFile.MP4
assoc # 文件类型关联的软件对应注册表项(在两处同时删除就和使用命令行删除关联一样的效果):
# HKEY_CLASSES_ROOT
# HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\
重定向部分系统目录到当前文件夹:
@echo off
setlocal
# 设置"批处理文件名_Data"为存放数据的文件夹
set "rootfolder=%~dp0\%~n0_Data"
# 修改常用系统文件夹路径,核心思想是修改目录变量
set "ProgramData=%rootfolder%\ProgramData"
set "UserProfile=%rootfolder%\UserProfile"
set "LocalAppData=%UserProfile%\AppData\Local"
set "AppData=%UserProfile%\AppData\Roaming"
if not exist "%rootfolder%" mkdir "%rootfolder%"
if not exist "%ProgramData%" mkdir "%ProgramData%"
if not exist "%UserProfile%" mkdir "%UserProfile%"
if not exist "%UserProfile%\AppData" mkdir "%UserProfile%\AppData"
if not exist "%LocalAppData%" mkdir "%LocalAppData%"
if not exist "%AppData%" mkdir "%AppData%"
# 把批处理命名为目标exe同名,并放在同一个目录下,双击批处理即可运行exe
start "" "%~n0.exe"
endlocal
win11右键菜单更改:
# win11右键菜单更改
# Win10模式
.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve
reg/f /im explorer.exe
taskkill start explorer.exe
# win11模式
.exe delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
reg/f /im explorer.exe
taskkill start explorer.exe
清理任务栏图标记录:
# 关闭Windows外壳程序explorer
/f /im explorer.exe
taskkill # 清理系统图标缓存数据库
-h -s -r "%userprofile%\AppData\Local\IconCache.db"
attrib del /f "%userprofile%\AppData\Local\IconCache.db"
/s /d -h -s -r "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\*"
attrib del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_32.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_96.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_102.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_256.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_1024.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_idx.db"
del /f "%userprofile%\AppData\Local\Microsoft\Windows\Explorer\thumbcache_sr.db"
# 清理 系统托盘记忆的图标
echo y|reg delete "HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" /v IconStreams
echo y|reg delete "HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" /v PastIconsStream
# 重启Windows外壳程序explorer
start explorer
注册表相关
打开注册表regedit
设置中,“安装的应用”项目存放位置(根据DisplayName
判断):
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
此电脑中各种虚拟盘符对应注册表项:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace
手动添加文件右键菜单:
进入 HKEY_CLASSES_ROOT\*\shell\
在下面新建一项 Editplus
在新建的项目中,再新建一个项 command
之后在【HKEY_CLASSES_ROOT\*\shell\Editplus\command\】的默认值中,写入Editplus的绝对路径,并在后面添加 %1 。比如:C:\Program Files\EditPlus\editplus.exe %1
如果要指定图标,可以在【HKEY_CLASSES_ROOT\*\shell\Editplus】中添加字符串值,名字填 icon ,值填ico图标路径或者exe文件路径
如果需要多级菜单,在【HKEY_CLASSES_ROOT\*\shell\Editplus】中添加字符串值 SubCommands ,值不用填写,然后在下面新建一项 shell ,再在下面填新建你要显示在二级菜单中的项,并添加command项指定要运行的程序。多级菜单以此类推。
路径参数:
%1 文件路径
%2 系统默认的打印机
%3 文件扇区
%4 端口
%D 文件路径
%L 文件长路径
%V 文件路径
%W 当前文件的父目录的路径
关闭ms-gamingoverlay弹框:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\GameDVR
,把AppCaptureEnabled
这个键值修改为0HKEY_CURRENT_USER\System\GameConfigStore
,把GameDVR_Enabled
这个键值修改为0暂停Windows更新至2099年(新建reg格式文件粘贴再运行):
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings]
"FlightSettingsMaxPauseDays"=dword:00000e42
"PauseFeatureUpdatesStartTime"="2020-01-01T00:00:01Z"
"PauseFeatureUpdatesEndTime"="2099-01-01T00:00:02Z"
"PauseQualityUpdatesStartTime"="2020-01-01T00:00:01Z"
"PauseQualityUpdatesEndTime"="2099-01-01T00:00:02Z"
"PauseUpdatesStartTime"="2020-01-01T00:00:01Z"
"PauseUpdatesExpiryTime"="2099-01-01T00:00:02Z"
Veracrypt常用命令
# 加载加密卷
veracrypt /beep /volume \Device\Harddisk0\Partition2 /password "123" /keyfile "1.txt" /auto /letter D /explore /quit
# 卸载加密卷
veracrypt /beep /dismount D /quit
命令参数解析:
/beep
或/b
:加载成功就播放一下提示音;/dismount
或/d
:卸载加密卷;/volume
或/v
:指定磁盘分卷名或文件路径;/password
或/p
:指定密码;/keyfile
或/k
:指定密钥位置;/letter
或/l
:指定分配的盘符,要和/auto
或/a
一起用才生效;/explore
或/e
:若加载成功,就打开该磁盘;/quit
或/q
:退出软件,否则每执行一次命令就新开一个窗口;VirtualBox常用命令
VBoxManage默认在C:\Program Files\Oracle\VirtualBox\VBoxManage.exe
,退出独占键盘和鼠标的默认快捷键是右边的Ctrl+Alt
。
# 压缩虚拟机
VBoxManage modifyhd D:\centos.vdi --compact
# 查看所有的虚拟磁盘
VBoxManage list hdds
# 删除虚拟磁盘(虚拟硬盘的文件也会被删除)
VBoxManage closemedium disk "<虚拟硬盘完整路径>" --delete
使用VirtualBox从本地硬盘启动系统,参考Using a Raw Host Hard Disk From a Guest:
1、确定硬盘DeviceID,或硬盘名称:
# Windows下查看硬盘DeviceID
wmic diskdrive list brief /format:list
# Linux下查看硬盘信息有很多种方法,以下任选一种即可
sudo fdisk -l
sudo df -h
sudo lshw -class disk
sudo cat /proc/partitions
sudo parted -l
2、创建vmdk,指向实体硬盘:
# Windows下的命令
# 使用管理员进入cmd执行,而且以后如果要使用该创建的vmdk要用管理员运行Virtalbox
VBoxManage internalcommands createrawvmdk -filename "D:\physicDrive.vmdk" -rawdisk \\.\PHYSICALDRIVE0
# 还可以指定使用哪几个分卷(ESP和MSR等EFI分区记得选上,不然没法启动系统)
VBoxManage internalcommands createrawvmdk -filename "D:\physicDrive.vmdk" -rawdisk \\.\PHYSICALDRIVE0 -partitions 1,2,3
# Linux下要先设置读写权限,而且以后每次使用该创建的vmdk都要设置读写权限
sudo chmod 666 /dev/nvme0*
sudo chmod 666 /dev/sda*
# 可以给同一个虚拟机创建多个不同的虚拟硬盘
VBoxManage internalcommands createrawvmdk -filename "physicDrive_nvme0n1.vmdk" -rawdisk /dev/nvme0n1 -relative
VBoxManage internalcommands createrawvmdk -filename "physicDrive_sda.vmdk" -rawdisk /dev/sda -partitions 1,2,3 -relative
3、打开Virtualbox,创建虚拟机:
VBoxManage modifyvm --pciattach
或VBoxManage modifyvm --pcidetach
来启用或禁用PCI
Passthrough,并在虚拟机里安装显卡驱动;# 安装并配置用户名、邮箱
sudo apt-get install git
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
# github通过SSH令牌进行身份验证
# 生成公钥
ssh-keygen -t rsa -C "你注册github时的邮箱"
# 查看公钥
gedit ~/.ssh/id_rsa.pub
# 上传公钥到github:打开github网站settings->SSH and GPGkeys->new SSH key->粘贴公钥
# 测试密钥是否添加成功:
ssh -T git@github.com
# 查看远程仓库
git remote -v
# 取消链接远程仓库,仓库别名通常是origin
git remote rm [远程仓库别名]
# 把当前文件夹链接到远程仓库,仓库别名通常是origin
git remote add [远程仓库别名] [ssh-url]
# 初始化本地仓库
git init
git remote add origin git@github.com:[username]/[repo name].git
# 上传到github
git add --all
git commit -m "update"
git push -u origin master
# 不删除项目情况下删除所有commit记录
# 原理是新建分支->文件移至新分支->提交更改(本地)->删除原分支->把新分支改名为master->提交至github)(需要重新上传所有文件):
git checkout --orphan latest_branch
git add -A
git commit -am "update"
git branch -D master
git branch -m master
git push -f origin master
官网:FFmpeg
# 列出所有支持的格式(也就是-f后面可以接的参数)
ffmpeg -formats
# 查看支持的编码器(也就是-vcodec后面可以接的参数)
ffmpeg -codecs
# 查看支持的滤镜(也就是-vf后面可以接的参数):
ffmpeg -filters
# 显示所有可用的硬件加速器(即GPU加速,需下载显卡相关的驱动并使用显卡相关的解码器及编码器)
ffmpeg.exe -hwaccels
# 获取视频信息
ffmpeg -i video.mp4
# 视频格式转换并重新编码(没有指定任何编码器或copy则默认重新编码),-f指定转码的格式,比如flv转成mp4,如果不指定则自动检测输出文件的后缀;-y表示若输出文件存在,则自动覆盖输出文件,而-n则表示不要覆盖输出文件
ffmpeg -i input.flv -f mp4 -y output.mp4
# -acodec copy:音频流执行copy,视频流重新解码、编码;注意,所有的编码指令都应在输出参数前面指定
ffmpeg -i input.mp4 -acodec copy -f mp4 output.mp4
# -vcodec copy:视频流执行copy,音频流重新解码、编码
ffmpeg -i input.mp4 -vcodec copy -f mp4 output.mp4
# -codec copy:音频流和视频流都执行copy,不重新解码、编码
ffmpeg -i input.mp4 -codec copy -f mp4 output.mp4
合并视频方法一,在视频所在文件夹中新建一个txt文件,把要合并的视频文件按顺序写上,比如filelist.txt:
file '1.mp4'
file '2.mp4'
file '3.mp4'
(以上文件内容可以用dir /b /s /a-d > filelist.txt
命令生成文件列表再修改,其中/s
表示递归遍历,/a-d
表示只列出文件)
然后执行:
# 方法一:合并mp4,使用concat demuxer方法,该方法要求视频音频的属性完全一样,且不会再进行解码、编码,速度较快
ffmpeg -f concat -i filelist.txt -c copy output.mp4
# 方法二:合并mp4,使用concat filter方法,该方法要求视频之间的分辨率和帧率一致,支持合并的同时重新解码、编码视频
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -filter_complex concat=n=4:v=1:a=1 -f mp4 output.mp4
# 方法三:ts格式可以使用concat protocol方法,直接在参数里指定concat的文件名,类似Linux中的cat命令
ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy output.ts
# 先合并ts,然后将合并后的ts重新编码、转码为mp4
ffmpeg -f concat -i filelist.txt -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
# mp4转为ts需要指定过滤器,-vbsf指定视频过滤器
ffmpeg -i input.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb output.ts
# 其他的一些常用编码器
# mp4转为webm
ffmpeg -i input.mp4 -c:v libvpx -c:a aac output.webm
# mp4转flv,-g可以设置关键帧间隔,比如45帧
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -g 45 output.flv
# 结合cmd的循环命令,可以批量重新解码、编码
for %%a in ("*.mp4") do ffmpeg -i "%%a" -c:v libx264 -c:a aac -y "%%a".mp4
其他常用命令:
# 视频压缩,-crf设置视频质量,取值范围为0~51,数值越大,画质越差,生成的文件就越小,一般取18即可让输出视频质量和输入视频相当;-r设置视频的帧率;-preset指定的编码速度越慢,获得的压缩效率就越高,取值有veryslow、slower、slow、medium、fast、faster、veryfast、superfast、ultrafast
ffmpeg -i input.mp4 -threads 2 -vcodec libx264 -acodec copy -preset veryslow -r 60 -crf 18 output.mp4
# 获取视频分辨率
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4
# 调整视频分辨率,比如调整为w:1920 h:1080;如果需要保持纵横比,那么就指定宽和高的其中一个,另一个设置为-1,比如-1:720
ffmpeg -i input.mp4 -vf scale=1920:1080 -preset veryslow -crf 18 output.mp4
# 调整视频分辨率时,支持使用变量计算宽高,比如宽和高都减少一半
ffmpeg -i input.mp4 -vf "scale=iw/2:ih/2" -preset veryslow -crf 18 output.mp4
# 视频切割
# 读取input.mp4文件,并将其转换为HLS格式,并生成HLS播放列表文件output.m3u8和对应的媒体切片文件output_001.ts、output_002.ts等等
# 其中-hls_time指定HLS切片时长,单位为秒;-hls_list_size指定HLS播放列表中切片数量,为0则表示生成无限大小的播放列表;-hls_segment_filename指定HLS切片文件名
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -hls_time 10 -hls_list_size 0 -hls_segment_filename "output_%03d.ts" output.m3u8
# 另一种切割方法
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -segment_time 10 -segment_format mpegts -segment_list output.m3u8 output_%03d.ts
# 音视频分离
# -an:audio no,只保留视频,去除音频
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
# -vn:video no,只保留音频,去除视频
ffmpeg -i input.mp4 -acodec copy -vn output.mp4
# 只保留音频,去除视频,且导出为MP3格式
ffmpeg -i input.mp4 -vn -acodec libmp3lame -ab 320k -ar 44100 -f mp3 output.mp3
# 截取视频,-ss指定开始时间、-t指定持续时间,或用-to指定结束时间,单位为秒,-s指定分辨率,但是直接截取可能会导致截取时间点不准确以及开头黑屏
ffmpeg -i input.mp4 -ss 00:01:10.0 -t 00:00:05 -s 1280x720 -codec copy -f flv output.flv
# 为了避免以上问题,可进行重新编码
ffmpeg -i input.mp4 -ss 00:00:01.123 -t 00:00:05 -c:v libx264 -c:a aac output.mp4
# 如果对准确度要求不高,可按关键帧截取视频,这样更快,注意,-accurate_seek必须放在-i参数之前
ffmpeg -ss 10 -t 5 -accurate_seek -i input.mp4 -codec copy output.mp4
# 顺时针旋转90°
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
# 逆时针旋转90°
ffmpeg -i input.mp4 -vf "transpose=2" output.mp4
# 水平翻转
ffmpeg -i input.mp4 -vf hflip output.mp4
# 垂直翻转
ffmpeg -i input.mp4 -vf vflip output.mp4
# 视频倒放、音频不变
ffmpeg -i input.mp4 -vf reverse reversed_video.mp4
# 音频倒放,视频不变
ffmpeg.exe -i input.mp4 -map 0 -c:v copy -af "areverse" reversed_audio.mp4
# 音视频都倒放
ffmpeg -i input.mp4 -vf reverse -af areverse -preset superfast reversed.mp4
# 两倍速播放,setpts=PTS/2指视频变为2倍速,atempo=2指音频变为2倍速,对音视频进行加速时,如果不想丢帧,可以用-r参数指定输出视频FPS,用-ar参数指定音频采样率(Hz)
ffmpeg -i input.mp4 -r 60 -vf setpts=PTS/2 -af atempo=2 output.mp4
# 音量调整为80%
ffmpeg -i input.mp4 -af "volume=0.8" output.mp4
# hstack:左右拼接视频;vstack:上下拼接视频
ffmpeg -i input1.mp4 -i input2.mp4 -lavfi hstack output.mp4
# 3个视频左右拼接
ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -lavfi hstack=inputs=3 output.mp4
# 字幕格式转换
ffmpeg -i subtitle.srt subtitle.ass
# 添加硬字幕(srt或ass格式字幕)
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output_srt.mp4
ffmpeg -i input.mp4 -vf ass=subtitle.ass output_ass.mp4
# 添加软字幕(srt或ass格式同样操作)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s mov_text -metadata:s:s:0 language=chi ouptut_chi.mp4
# 添加多通道软字幕
ffmpeg -i input.mp4 -i ch.srt -i en.srt -map 0 -map 1 -map 2 -c copy -c:s mov_text -metadata:s:s:0 language=chi -metadata:s:s:1 language=eng output_chi_eng.mp4
# 提取软字幕(将第二个轨道subrip字幕轨道提取成srt文件,通过视频信息可查看第几个Stream是字幕)
ffmpeg -i input.mp4 -map "0:2" output.srt
一些常见问题:
# 合并mp4时,若出现Unsafe file name错误,则添加参数"-safe 0"
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4
# 解决时间轴的损坏
# 方法一:分离出视频、音频,再混合视频和音频,重新生成文件
ffmpeg -i input.mp4 -map 0:v -vcodec copy -bsf:v h264_mp4toannexb output_video.mp4
ffmpeg -i input.mp4 -vn output_audio.wav
ffmpeg -i output_video.mp4 -i output_audio.wav -c copy output_fixed.mp4
# 方法二:设定帧率为60fps(或其他想要的帧率),重新封装
ffmpeg -fflags +genpts -r 60 -i input.mp4 -vcodec copy output_fixed.mp4
# 方法三:如果两个视频的time_base(即tbn)不一样,合并之后时间轴出错可以用以下方法修复(按需取值)
ffmpeg -i input.mp4 -c:v copy -video_track_timescale 12800 output.mp4
pandoc官网,文档,安装完要添加到环境变量里;如果要生成PDF,还要安装(任选一个即可):TeX Live、MiKTeX。
pandoc -s --toc --toc-depth=6 --katex="file:///path/to/katexfolder/" --css=cssfile.css -H jsfile.js --embed-resources --metadata title="title" infile.md -o outfile.html
pandoc -s --pdf-engine="path/to/xelatex.exe" -V mainfont="SimSun.ttc" --template="path/to/template.latex" -f markdown -t pdf infile.md -o outfile.pdf
命令参数解析:
-f FORMAT
、--from=FORMAT
:指定输入文件的格式(可以通过文件后缀自动识别);-t FORMAT
、--to=FORMAT
:指定输出文件的格式(可以通过文件后缀自动识别);-s
、--standalone
:生成一个独立的HTML或LaTeX文件,包含完整的文档头和尾;如果不使用该选项,默认情况下,pandoc只会生成文档片段,比如网页就只有内容,不包含html、head、body等标签;-o FILENAME
、--output=FILENAME
:指定输出文件的名称和路径;--css=CSSFILE
:使用自定义的css样式;pandoc似乎无法自定义javascript,不过可以通过-H
、-B
、-A
后面加文件名,来间接添加,这几个参数的意思分别是在head中、在body前、在body后插入文件的内容,不过要记得在代码前后加script标签;--embed-resources[=true|false]
:生成一个没有外部依赖关系的独立HTML文件,比如把css放进html中不再以link的形式引用,把图片、字体等以base64的形式嵌入到网页中;类似的参数还有--self-contained
;--mathml
、--katex[=URL]
、--mathjax[=URL]
:指定数学公式输出的格式为MathML、KaTeX或者MathJax;其中MathML是pandoc内置的,但是对部分公式支持不好(比如上下划线、箭头等过短);KaTeX、MathJax不指定URL则使用默认cdn加载,不过可以本地化,其中KaTeX的URL指向带有katex.min.js
和katex.min.css
的文件夹,2.x版本的MathJax的URL指向MathJax.js
文件,3.x版本指向./MathJax/es5/tex-svg.js
文件;--highlight-style=STYLE
:设置代码块的语法高亮的样式,默认是pygments,STYLE
的可选值可以通过pandoc --list-highlight-styles
命令列出,支持的编程语言可以通过pandoc --list-highlight-languages
命令列出;--toc
、--toc-depth=6
:生成TOC,默认生成最多3级目录,可以改为比如6级目录;-M KEY[=VAL]
、--metadata=KEY[:VAL]
:设置文档元数据;比如设置文档日期-M date='1970-01-01'
,设置标题--metadata title="xxx"
;-V KEY[=VAL]
、--variable=KEY[:VAL]
:设置Pandoc变量值,可以在文档中使用KEY来引用该变量;
-V mainfont="SimSun"
,Linux下则是-V CJKmainfont="KaiTi"
;要找到支持的中文字体,在Linux下可以通过fc-list :lang=zh
命令列出,Windows下如果安装了TeX
Live,也可以使用该命令;-V geometry:"top=2cm, bottom=1.5cm, left=2cm, right=2cm"
;--pdf-engine=xelatex
:指定pdf解析引擎为xelatex,默认是没有引擎的,需要另外安装;--template=TEMPLATENAME
:指定导出pdf时使用的模板,这里推荐Eisvogel模板;
C:\Users\USERNAME\AppData\Roaming\pandoc\templates\
;/Users/USERNAME/.local/share/pandoc/templates/
或者/Users/USERNAME/.pandoc/templates/
;--extract-media=DIR
:比如从.docx转为.md,默认是不提取嵌入在.docx中的图片的,加上该命令后,图片就会提取到指定的目录;--shift-heading-level-by=NUMBER
:改变标题层级;比如把NUMBER
设置成1,那么在生成的文件中,一级标题#
则会变成二级标题##
,而NUMBER=-1
则可以把二级标题改为一级标题;--eol=crlf|lf|native
:指定生成文件的换行符;--quiet
:忽略所有WARNING;比如HTML5要求所有网页都必须指定一个非空标题,如果使用了-s
命令,就必须通过--metadata title="xxx"
,或使用YAML格式的header,或文章开头使用% title
等方式来指定标题,否则会出现WARNING,这时使用该参数可以忽略警告,忽略后将使用文件名作为默认的标题;注意:如果markdown中使用的图片等外部文件使用了相对路径,那么需要在markdown所在的目录下运行pandoc,否则找的是pandoc所在的目录,就会报错说找不到文件。
注意:用pandoc将markdown导出为html,数学公式会在annotation标签下保留latex源码,如果不想保留,可以通过以下命令删除(浏览器console执行,然后保存网页;部分浏览器保存后页内锚点会变成绝对路径,且文件开头会出现保存时间的注释,需修改):
function(){
(//填入公式保存位置的选择器
=['annotation', 'span[class="katex-mathml"]', 'script[type="math\/tex"]'];
tagStrs.forEach(
tagStrsfunction(tagStr){
var tagElements = document.querySelectorAll(tagStr);
for(let i = 0; i < tagElements.length; i++){
.parentNode.removeChild(tagElements[i])
tagElements[i]
}
};
) })()
附一个仿Typora的css:
html {scroll-behavior: smooth;
}
body {/* 网页字体1rem,pdf字体10.5px,生成pdf时需修改字体大小*/
font-size: 1rem;
/* font-size: 10.5px; */
line-height: 1.6;
tab-size: 4;
color: rgb(51, 51, 51);
font-family: Microsoft YaHei,"Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, 'Segoe UI Emoji', sans-serif;
-webkit-font-smoothing: antialiased;
/* TOC的宽度是300px,根据TOC进行修改(生成pdf时需把这部分注释掉) */
position: relative;
top: 0;
left: 300px;
width: calc(90% - 300px);
padding: 2em 5%;
},h2,h3,h4,h5,h6 {
h1position: relative;
margin-top: 1rem;
margin-bottom: 1rem;
padding-bottom: 0;
font-weight: bold;
line-height: 1.4;
cursor: text;
}
h1 {font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}
h2 {font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}
h3 {font-size: 1.5em;
line-height: 1.43;
}font-size: 1.25em;}
h4 {font-size: 1em;}
h5 {font-size: 1em;color: #777;}
h6 {,blockquote{ margin: 0.8em 0 !important; }
p,ol,dl,table{margin: 0.8em 0;}
ul>ol,li>ul {margin: 0 0;}
li
a {color: #4183C4;
text-decoration: none;
}
hr {height: 2px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
overflow: hidden;
box-sizing: content-box;
}.first {display: inline-block;}
li p,ol {padding-left: 20px;}
ul:first-child,ol:first-child {margin-top: 0;}
ul:last-child,ol:last-child {margin-bottom: 0;}
ul
blockquote {border-left: 4px solid #dfe2e5 !important;
padding: 0 15px;
color: #777777 !important;
background-color: #ffffff !important;
}padding-right: 0;}
blockquote blockquote {
table {padding: 0;
word-break: initial;
border-collapse: collapse;
}
table tr {border: 1px solid #dfe2e5;
margin: 0;
padding: 0;
}:nth-child(2n),thead {background-color: #f8f8f8;}
table tr
table th {font-weight: normal;
text-align: unset;
border-bottom: 0;
border: 1px solid #dfe2e5;
margin: 0;
padding: 6px 13px;
}
table td {border: 1px solid #dfe2e5;
margin: 0;
padding: 6px 13px;
}:first-child,table td:first-child {margin-top: 0;}
table th:last-child,table td:last-child {margin-bottom: 0;}
table th
tt {border: 1px solid #e7eaed;
background-color: #f8f8f8;
border-radius: 3px;
padding: 2px 4px 0px 4px;
font-size: 0.9em;
}
code {border: 1px solid #e7eaed;
background-color: #f3f4f4;
border-radius: 3px;
padding: 0 2px 0 2px;
font-size: 0.9em;
}
img {width: 50%;
height: 50%;
display: block;
vertical-align: middle;
image-orientation: from-image;
margin: auto;
}
figcaption {text-align: center;
}@page {
size: A4;
/* 调整生成的PDF中上下左右空白的大小 */
margin: 14mm 19.5mm;
}
/* 代码块显示行号,要求代码块的每行最外面有且只有一个span,否则行号会计算出错,目前pandoc测试没问题 */
>code{
precounter-reset: linenumber;
display: block;
white-space: pre;
overflow: auto !important;
padding: 0.2em;
border-radius: 7px;
}>code>span {
precounter-increment: linenumber;
display: inline-block;
line-height: 1.25em !important;
}>code>span::before {
precontent: counter(linenumber);
display: inline-block;
font-size: 0.9em;
color: #999;
min-width: 1.8em;
margin-right: 0.5em;
padding-right: 0.25em;
text-align: right;
border-right: 1px solid #999;
line-height: 1.9em;
user-select: none;
pointer-events: none;
}
/* pandoc生成的TOC标签的id叫TOC,如果其他软件生成的id或class不一样就需要更改 */
#TOC {
font-size: 0.8rem;
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 100%;
padding: 32px 16px 48px 16px !important;
box-shadow: 0 0 4px rgba(150,150,150,0.33);
box-sizing: border-box;
overflow: auto;
scrollbar-color: #f5f5f5;
scrollbar-width: 1px;
}#TOC::-webkit-scrollbar{
width: 1px;
border-right: 1px solid #f5f5f5;
}#TOC a{
color: #333333;
text-decoration: none;
}#TOC a:hover{
color: #333333 !important;
text-decoration: underline !important;
}#TOC ul { list-style: none; }
#TOC li { margin-bottom: 0.25rem; }
/* 屏幕太小则隐藏TOC */
@media (max-width: 700px) {
#TOC { display: none; }
left: 0px; width: 90%; }
body { }
附一个实现导航栏高亮当前项的javascript,通过-H jsfile.js
参数导入:
<script type="text/javascript">
window.onload = function(){
/* 点击页内锚点平滑滚动,且不更新地址栏 */
document.querySelectorAll('a[href^="#"]').forEach(function(item,index,arr){
.addEventListener('click', function(e) {
item.preventDefault();
e//获取导航项对应的ID锚点的元素,通过ID获取就不会将比如点“.”当作类选择器,可以处理符号冲突
const target = document.getElementById(decodeURI((item.href.substring(item.href.indexOf('#')+1))));
if(target == null) { return; }
.scrollIntoView({ behavior: 'smooth' });
target;
})
})
/* 调用后,将TOC中当前导航项突出显示 */
const toc_a = document.querySelectorAll('#TOC a');
function updateTOC(){
const scrollPosition = window.scrollY;//获取页面滚动的垂直位置
let highlightTarget;
for(let i=toc_a.length-1; i>=0; i--){//从后往前遍历,就可以找到最接近当前滚动位置上方的导航项
const target = document.getElementById(decodeURI((toc_a[i].href.substring(toc_a[i].href.indexOf('#')+1))));//获取导航项对应的ID锚点的元素
if(target == null) { continue; }
const ItemPosition = target.offsetTop;//获取元素的垂直位置
if (scrollPosition > ItemPosition && typeof(highlightTarget) == "undefined") {//判断元素位置是否在当前滚动位置的上方
= toc_a[i];//记录要高亮的导航项
highlightTarget else if(typeof(highlightTarget) == "undefined" && i == 0) {//要是文章上方有的部分没有导航项与之对应,则将第一个导航项突出显示
} = toc_a[0];
highlightTarget
}
}.forEach( item => {
toc_a.style.fontWeight = "";//移除所有的突出显示样式
item;
})if(typeof(highlightTarget) == "undefined") { return; }
.style.fontWeight = "bold";//给当前的导航项添加突出显示样式
highlightTargetif(!isInViewPort(highlightTarget)){//如果当前的导航项超出可视区域,那么就将导航项垂直居中
.scrollIntoView({ block: "center"});
highlightTarget
}
}//判断元素是否在可视区域内
function isInViewPort(dom) {
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
const viewWidth = window.innerWidth || document.documentElement.clientWidth;
const { top, right, bottom, left } = dom.getBoundingClientRect();//当滚动条滚动时,top, left, bottom, right时刻会发生改变。
//如果一个元素在视窗之内,那么它的top、left大于等于0,且bottom、right小于等于视窗宽度
return (top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight);
}//停止滚动200ms后才更新TOC
let timer = null;
window.addEventListener('scroll', () => {
window.clearTimeout(timer);
= window.setTimeout(() => { updateTOC() }, 200);
timer ;
});
}</script>
如果想让超链接(页内锚点除外)在新标签页打开,可以在head中插入如下代码:
<base target="_blank">
Windows下使用pandoc批量转换markdown文件(使用前根据目录结构建好文件夹并放入文件):
echo off
65001
chcp SET root_dir=%cd%
SET source=%root_dir%\_source
SET lib=%root_dir%\_lib
SET output=%root_dir%\output
%output%
mkdir
for /R %source% %%i in (*.md) do (
cd %%~dpi
echo processing %%~ni%%~xi
/c pandoc -s --toc --toc-depth=6 --katex="file:///%lib:\=/%/katex/" --css="%lib%\blog.css" -H "%lib%\blog.js" --embed-resources --metadata title="%%~ni" %%i -o "%output%\%%~ni.html"
cmd cd %root_dir%
)
pause
Linux下使用pandoc批量转换markdown文件(使用前根据目录结构建好文件夹并放入文件):
root_dir=$(pwd)
source="${root_dir}/_source"
lib="${root_dir}/_lib"
output="${root_dir}/output"
mkdir "${output}"
function read_dir() {
for file in `ls $1`; do
if [ -d "${1}/${file}" ]; then
# 如果是文件夹,则递归
read_dir "${1}/${file}"
else
# 如果是文件,则执行命令
if echo "${file}" | grep -q -E '\.md$'; then
echo "processing ${file}"
cd $1
${lib}/pandoc/bin/pandoc -s --toc --toc-depth=6 --katex="file:///${lib}/katex/" --css="${lib}/blog.css" -H "${lib}/blog.js" --embed-resources --metadata title="${file%%.*}" "${1}/${file}" -o "${output}/${file%%.*}.html"
cd ${root_dir}
fi
fi
done
}
read_dir ${source}
VSCode
1、安装Markdown All in One、Markdown Preview Enhanced插件,然后下载prince,并将prince的exe所在目录添加进Path环境变量;
2、打开VSCode,按Ctrl+Shift+P
,输入Markdown Preview
Enhanced: Customize Css,文件结构如下:
/* .markdown-preview.markdown-preview是正文部分的div的class */
.markdown-preview.markdown-preview {
/* css... */
&.prince {
/* prince专属配置(可以覆盖外面写的css,可以把pdf和html不同的部分放进来,必须放在这里才能生效) */
font-size: 10.5px;
}
}/* css... */
将前面pandoc的css稍作修改即可:
body
选择器改为.markdown-preview.markdown-preview
(像字体大小这些必须这样设置才能生效);.md-toc
;/* 去除TOC前面的三角形、正方形等list图标 */
.md-toc summary { list-style: none; }
.md-toc summary::-webkit-details-marker { display:none; }
.md-toc details div {
display: block !important;
list-style: none !important;
}/* 去掉TOC中奇怪的空行 */
.md-toc ol {margin-bottom: 0;}
&.prince {
/* pdf需更改字体大小,且不需要自己设置TOC,要删掉为TOC预留的位置 */
font-size: 10.5px;
position: static;
top: 0;
left: 0;
width: 100%;
padding: 0;
@page {
@bottom {
/* PDF底部加页码(放在.markdown-preview.markdown-preview或&.prince等里面才会生效) */
: Microsoft YaHei;
font-family: 0.5rem;
font-size: counter(page) "/" counter(pages)
content
}
} }
3、如果要生成带侧边栏TOC的html,进入VSCode的插件选项->进入Markdown
Preview Enhanced插件的设置->找到Enable Script
Execution并勾选,并在md文件的最前面加上如下代码(其中embed_local_images
如果被设置为true,那么所有的本地图片将会以base64的形式嵌入到html中):
---
html:
embed_local_images: true
toc: true
depth_from: 1
depth_to: 6
ordered: false
---
4、VSCode打开markdown文档->右键->MPE打开侧边预览,右边打开的窗口->右键->PDF(prince)->生成pdf文件;右键->HTML->HTML(offline)->生成html;
Typora
如果Typora想把markdown中使用的图片以base64的形式嵌入到导出的html中,需要下载compact_html,并在Typora设置->导出->html->勾选运行自定义命令->输入"D:\compact_html.exe" "${outputPath}"
(改为你的compact_html.exe路径)
Hexo
Hexo基于Node.js,因此可以使用Node.js的gulp,来实现将图片以base64的形式嵌入到导出的html中,并将公式由mathjax转为svg,同时还可以精简html。
先安装所需模块:
# gulp要安装两次,一次全局,一次项目内
sudo npm install --global gulp-cli
npm install gulp --save-dev
npm install gulp-mathjax-page --save-dev
npm install gulp-html-minifier --save-dev
然后新建gulpfile.js如下(Hexo生成的html在./public
下,如果是其他路径就自行更改):
var gulp = require('gulp');
var mathjax = require('gulp-mathjax-page');
var htmlmin = require('gulp-html-minifier');
function img2base64(){
let through = require('through2');
let path = require('path');
let fs = require('fs');
function transferImage(file, encoding, callback){
if (file.isNull()) {
return callback(null, file);
}if (file.isStream()) {
return callback(createError(file, 'Streaming not supported'));
}let content = file.contents.toString();
//比如音频,regx则是 /(<source[\s\S]*?src\s*=\s*[\"|\'])(.*?)([\"|\'][\s\S]*?>)/g
let rule = /(<img[\s\S]*?src\s*=\s*[\"|\'])(.*?)([\"|\'][\s\S]*?>)/g;//注意,这样无法排除注释里的img标签,如果找不到对应的图片,会报错
let imgList = content.match(rule) || [];
if (imgList.length) {
.forEach(function(item) {
imgListlet imageURL = item.replace(rule, '$2');
if(imageURL.startsWith("data")){//防止已经base64转码的src再转码
return false;
}if(/^http|https:/.test(imageURL)) {//排除网络图片
return false;
}let route = path.join(__dirname, 'public', decodeURI(imageURL.replace(/\/prefix/,'')));//生成的图片地址和实际文件路径不一样,需要修正(自行更改)
try{
let filepath = fs.realpathSync(route);
let imageContent = Buffer.from(fs.readFileSync(filepath)).toString('base64');
let extname = path.extname(imageURL).slice(1);
//比如音频,base64的开头则是 data:audio/mpeg;base64,
= content.replace(item, item.replace(imageURL,'data:image/' + extname.toLowerCase() + ';base64,' + imageContent));
content catch(err){
}console.log(err);//文件不存在就输出错误然后跳过
};
})
}.contents = Buffer.from(content);
filethis.push(file);
callback(null, file);
}return through.obj(transferImage);
}
.task('mytask1', async() => {
gulp.src('./public/**/*.html')
gulp.pipe(mathjax({ //latex公式生成svg
mjpageConfig: {
format: ['TeX'],
singleDollars: true,
cssInline: false,
mhchem: {legacy: true}
,
}mjnodeConfig: {
svg: true,
css: false,
speakText: false
}
})).pipe(img2base64())//图片转base64嵌入到html中
.pipe(htmlmin({
removeComments: true,//清除HTML注释
collapseBooleanAttributes: false,//省略布尔属性的值 <input checked="true"/> ==> <input />
removeEmptyAttributes: false,//删除所有空格作属性值 <input id="" /> ==> <input />
collapseWhitespace: true,//压缩HTML
minifyJS: true,//压缩页面JS
minifyCSS: true//压缩页面CSS
})).pipe(gulp.dest('./public'))
})
最后执行gulp mytask1
关于使用Markdown的一些注意事项:
1、由于Windows和Linux路径分隔符不一样,插入的外部文件(如图片)不要带路径,最好和markdown文件放在同一目录,直接写文件名即可;
2、标题尽量不要出现Latex公式,否则生成的HTML或PDF的TOC点击后无法跳转(对于HTML可以F12改一下锚点id);
3、尽量不要对Latex公式加粗、斜体、高亮、下划线、删除线等,像VSCode和MarkText就不会解析这些**
和==
等,而是直接显示到生成的HTML中;
4、行内公式要用两个$
包裹,而不要用两个$$
包裹;单独一行的公式(即用两个$$
包裹的)不仅$$
要换行,而且$$
前后都要留有空行,否则MarkText不能正确解析;
5、如果公式要换行,要使用环境包裹,比如\begin{aligned}...\end{aligned}
或\begin{array}{cc}...\end{array}
等,而且要用\\
换行,而不要用\newline
,否则pandoc的mathml无法识别;
6、虚线分割的矩阵,包括\begin{array}{cc:c}...\end{array}
和\hdashline
,pandoc的mathml都无法识别;
7、微分符号要写做\mathrm{d}
,不要简写为\rm d
,否则pandoc的mathml无法识别;
8、pandoc的mathml不支持verb|...|
(其中两边的|
可以换成任意除字母、空格、星号外的任意不与之间内容冲突的符号,只是习惯用|
);
9、Latex中的中文最好用\text{...}
包裹,否则pandoc的KaTex导出的html会报warning;
10、空集最好写\emptyset
,而不要写做\empty
,否则VSCode可能不识别(更新后好像已经支持了);
11、尽量不要出现两个连续的大括号,比如{{xxx}}
,否则会与hexo的语法冲突,报错Nunjucks
Error;
12、尽量统一换行符,比如用Linux换行符\n
,并统一使用UTF-8。
SDK Platform Tools下载地址:官网、国内专用
#启动adb服务
adb start-server
#关闭adb服务
adb kill-server
#查看连接adb的设备
adb devices
#使用基于pair的无线调试
adb pair <IP[:PORT]> [PAIRING CODE]
#连接网络设备
adb connect <IP[:PORT]>
#断开网络设备的链接
adb disconnect [IP[:PORT]]
#重启手机
adb reboot
#通过adb进入bootloader:
adb reboot bootloader
#通过adb进入recovery:
adb reboot recovery
#重新挂载文件系统
adb remount
#获取su权限
adb shell su
#获取当前(前台)用户的ID
adb shell am get-current-user
#获取所有现有用户的列表
adb shell pm list users
#查看支持最多用户数
adb shell pm get-max-users
#创建新用户并返回ID
adb shell pm create-user <userName>
#按ID移除特定用户
adb shell pm remove-user <userId>
#按ID启动用户
adb shell am start-user <userId>
#按ID将新用户切到前台来
adb shell am switch-user <userId>
#查看切换用户是否成功(u0即表示userId=0的用户应用正处于前台)
adb shell dumpsys activity a | adb shell grep 'Hist '
#所有应用列表:
adb shell pm list packages
#为特定用户列出软件包
adb shell pm list packages --user <userId>
#查找某个app
adb shell pm list packages "关键字"
#系统应用列表:
adb shell pm list packages -s
#已停用的系统应用列表:
adb shell pm list packages -s -d
#已启用的系统应用列表:
adb shell pm list packages -s -e
#查看某个应用的详细信息
adb shell dumpsys package <packageName>
#打开app(比如:adb shell am start -n com.topjohnwu.magisk/com.topjohnwu.magisk.ui.MainActivity)
adb shell am start -n 包名/包名.活动名
#打开指定用户下的app
adb shell am start --user <userId> 包名/包名.活动名
#以action的方式打开app(以打开输入法设置为例)
adb shell am start -a android.settings.INPUT_METHOD_SETTINGS
#以指定category的方式打开app(以打开通讯录为例)
adb shell am start -c android.intent.category.APP_CONTACTS
#结合起来用
adb shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n 包名/包名.活动名
#启动服务
adb shell am startservice 包名/.活动名
#恢复出厂设置
adb shell am broadcast -a android.intent.action.MASTER_CLEAR
#强行停止与该app关联的所有进程
adb shell am force-stop <packageName>
#终止所有后台进程
adb shell am kill-all
#安装app(可以使用-g参数在安装时直接授予所有所需权限、-r替换已存在应用(即保留数据并安装新包)、-d忽略版本号安装(允许降级)、-l锁定应用(Android apk forward lock)):
#关于Android apk forward lock可查看http://developer.android.com/guide/appendix/market-filters.html
adb shell install app
#为特定用户安装软件包(用于多开应用)
adb install --user <userId> <apk_path>
#比如将已经安装在userId=0的应用,安装到userId=999的用户中
adb shell pm install -r --user 999 `adb shell pm path com.tencent.mm | awk -F':' '{print $2}'`
#卸载app:
adb shell uninstall <packageName>
#卸载系统app(-k 表示保存数据):
adb shell pm uninstall -k --user 0 <packageName>
#恢复卸载的app
adb shell cmd package install-existing <packageName>
#启用app:
adb shell pm enable <packageName>
#为特定用户启用app
adb shell pm enable --user <userId> <packageName>
#停用app(方式1):
adb shell pm disable <packageName>
#停用app(方式2):
adb shell pm disable-user <packageName>
#为特定用户停用app
adb shell pm disable --user <userId> <packageName>
#隐藏app(提示没有权限可能需要su):
adb shell pm hide <packageName>
#取消隐藏app:
adb shell pm unhide <packageName>
#去除app权限:
adb shell pm revoke <packageName>
#查看app路径:
adb shell pm path <packageName>
#截图
adb shell screencap /storage/emulated/0/test.png
#录屏(要结束录屏的话就按ctrl+c,或者可以设置最大录屏时间,单位是秒;默认比特率为4Mbps,可以通过--bit-rate更改;通过添加--bugreport参数还可以添加时间戳水印)
adb shell screenrecord --time-limit=120 --bit-rate 6000000 /mnt/sdcard/Download/test.mp4
#从手机提取文件(1为手机路径,2为电脑路径):
adb pull <path1> <path2>
#传送文件到手机(1为电脑路径,2为手机路径):
adb push <path1> <path2>
#将日志打印到电脑上
adb logcat > D:\log.txt
#获取当前打开的APP的包名和activity
adb shell dumpsys window | adb shell grep mFocusedApp
#获取手机内存信息
adb shell cat /proc/meminfo
#获取手机存储信息
adb shell df
#获取手机的序列号(两种方式)
adb get-serialno
adb shell getprop ro.serialno
#获取手机的IMEI(两种方式)
adb shell dumpsys iphonesubinfo
adb shell getprop gsm.baseband.imei
#获取手机厂商名称
adb shell getprop ro.product.brand
#获取手机设备类型
adb shell getprop ro.product.model
#获取Android版本
adb shell getprop ro.build.version.release
#获取api版本
adb shell getprop ro.build.version.sdk
#查看手机的分辨率(两种方式)
adb shell wm size
adb shell dumpsys window | adb shell grep init
#获取手机物理密度
adb shell wm density
#查看电池信息
adb shell dumpsys battery
#查看连接fastboot的设备
fastboot devices
#重启到系统
fastboot reboot
#重启到bootloader(注意部分机型这样做可能会导致系统损坏)
fastboot reboot bootloader
#重启到recovery(注意部分机型这样做可能会导致系统损坏)
fastboot reboot recovery
#刷入ROM(不同机型输入方式不同)
fastboot update update.zip
#oem解锁(不同机型解锁方式可能不同):
fastboot oem unlock
fastboot oem lock
#临时REC(比如TWRP,注意,部分机型的TWRP要刷在vendor_boot或recovery分区):
fastboot boot twrp-xxx.img
#使用sideload方式刷入永久REC(需要先进临时REC并且使用adb sideload功能):
adb sideload twrp-installer-xxx.zip
#直接通过fastboot刷入boot.img(比如用Magisk修补过的boot文件):
fastboot flash boot boot.img
#其他分区同理:
fastboot flash system system.img
#VAB分区时(不同机型的logo分区名字可能不同):
fastboot flash logo_a logo.img
fastboot flash logo_b logo.img
#擦除分区:
fastboot erase system
fastboot erase userdata
fastboot erase metadata
fastboot erase cache
#切换活动槽位为a或b(适用VAB分区的手机)
fastboot set_active a
fastboot set_active b
#adb可以看当前活动槽位
adb shell getprop ro.boot.slot_suffix
#删除所有magisk模块
adb wait-for-device shell magisk --remove-modules
APK-Splits的安装:
方法1,解压.apks
文件,得到若干个.apk
文件,这里假设分成base.apk、split_config.xxhdpi.apk、split_config.arm64_v8a.apk三部分,然后将这些.apk
文件文件复制到手机里,这里我们放到/sdcard/tmp/
目录下:
# 进入Shell命令行模式
adb shell
# 创建安装session
# (如果已经安装了base.apk,后续不用再装,但这里要使用包名来创建:pm install-create -r -p com.google.android.gm)
pm install-create
# 此时会返回一个结果,比如Success: created install session [1635978285],后续需使用该session ID
pm install-write 1635978285 base.apk /sdcard/tmp/base.apk
pm install-write 1635978285 split_config.xxhdpi.apk /sdcard/tmp/split_config.xxhdpi.apk
pm install-write 1635978285 split_config.arm64_v8a.apk /sdcard/tmp/split_config.arm64_v8a.apk
# 完成写入所有APK后,执行合并安装
pm install-commit 1635978285
方法2,使用官方提供的bundletool.jar安装,需先配置好Java环境:
# 先使用adb devices确认设备已连接
java -jar <bundletool.jar的路径> install-apks --apks=<.apks文件路径>
备注:Google Play
Store下载的应用是.aab
格式,.aab
转.apks
命令:
java -jar bundletool.jar build-apks --bundle=xxx.aab --output=xxx.apks
# 或
java -jar bundletool.jar build-apks --bundle=xxx.aab --output=xxx.apks --ks=xxxx.jks --ks-pass=pass:证书密码 --ks-key-alias=证书别名 --key-pass=pass:证书别名密码
备份应用命令:adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|nosystem] [<packages>]
-f <file>
:设置备份后的文件名和路径。比如"C:\backupfile.ab"
,扩展名是ab
;-apk|-noapk
:选择是否备份APK安装包,默认是只备份应用数据,不备份安装包的;-shared|-noshared
:是否备份SD卡中的应用数据;-all
:简单地表达“所有应用”的说法;-system|-nosystem
:这个参数决定-all
参数是否包含系统应用;<packages>
:指定备份要备份应用的包名;比如备份软件及数据adb backup -f filename.ab -apk -shared packagesName
,恢复就adb restore <filename.ab>
// 字符串md5加密,bit指定16位或32位,输出小写,要大写调用字符串的toUpperCase()
function md5(string,bit) {
function md5_RotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}function md5_AddUnsigned(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
= (lX & 0x80000000);
lX8 = (lY & 0x80000000);
lY8 = (lX & 0x40000000);
lX4 = (lY & 0x40000000);
lY4 = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
lResult if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else {
} return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}else {
} return (lResult ^ lX8 ^ lY8);
}
}function md5_F(x, y, z) {
return (x & y) | ((~x) & z);
}function md5_G(x, y, z) {
return (x & z) | (y & (~z));
}function md5_H(x, y, z) {
return (x ^ y ^ z);
}function md5_I(x, y, z) {
return (y ^ (x | (~z)));
}function md5_FF(a, b, c, d, x, s, ac) {
= md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac));
a return md5_AddUnsigned(md5_RotateLeft(a, s), b);
;
}function md5_GG(a, b, c, d, x, s, ac) {
= md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac));
a return md5_AddUnsigned(md5_RotateLeft(a, s), b);
;
}function md5_HH(a, b, c, d, x, s, ac) {
= md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac));
a return md5_AddUnsigned(md5_RotateLeft(a, s), b);
;
}function md5_II(a, b, c, d, x, s, ac) {
= md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac));
a return md5_AddUnsigned(md5_RotateLeft(a, s), b);
;
}function md5_ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
= (lByteCount - (lByteCount % 4)) / 4;
lWordCount = (lByteCount % 4) * 8;
lBytePosition = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
lWordArray[lWordCount] ++;
lByteCount
}= (lByteCount - (lByteCount % 4)) / 4;
lWordCount = (lByteCount % 4) * 8;
lBytePosition = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lWordCount] - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
lWordArray[lNumberOfWords return lWordArray;
;
}function md5_WordToHex(lValue) {
var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
= (lValue >>> (lCount * 8)) & 255;
lByte = "0" + lByte.toString(16);
WordToHexValue_temp = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
WordToHexValue
}return WordToHexValue;
;
}function md5_Utf8Encode(string) {
= string.replace(/\r\n/g, "\n");
string var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
+= String.fromCharCode(c);
utftext else if ((c > 127) && (c < 2048)) {
} += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
utftext else {
} += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
utftext
}
}return utftext;
;
}var x = Array();
var k, AA, BB, CC, DD, a, b, c, d;
var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
var S41 = 6, S42 = 10, S43 = 15, S44 = 21;
= md5_Utf8Encode(string);
string = md5_ConvertToWordArray(string);
x = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
a for (k = 0; k < x.length; k += 16) {
= a; BB = b; CC = c; DD = d;
AA = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
a = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
d = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
c = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
b = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
a = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
d = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
c = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
b = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
a = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
d = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
c = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
b = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
a = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
d = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
c = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
b = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
a = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
d = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
c = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
b = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
a = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453);
d = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
c = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
b = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
a = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
d = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
c = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
b = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
a = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
d = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
c = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
b = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
a = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
d = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
c = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
b = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
a = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
d = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
c = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
b = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
a = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
d = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
c = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
b = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
a = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
d = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
c = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
b = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244);
a = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
d = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
c = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
b = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
a = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
d = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
c = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
b = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
a = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
d = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314);
c = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
b = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
a = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
d = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
c = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
b = md5_AddUnsigned(a, AA);
a = md5_AddUnsigned(b, BB);
b = md5_AddUnsigned(c, CC);
c = md5_AddUnsigned(d, DD);
d
}if(bit==32){
return (md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase();
}return (md5_WordToHex(b) + md5_WordToHex(c)).toLowerCase();
}