目录

Linux命令行基础

学习本教程时,需要尝试命令,并且仔细看命令的运行的结果。 命令后的#号及其后边的文字不属于命令,不需要输入,但需要查看,这往往能够帮助学习和理解各条命令。本教程中出现的命令,都要尽可能记住,必要的时候,自己要查看其参数,以便在必要的时候能够使用合适的参数。务必要动手去输入,动脑去体会,不然是很难上手的。

GNU/Linux系统简介

Linux是一个系统内核,Linux系统即是以Linux为内核的系统,一些Linux系统内核之外的软件运用通常来自于GNU项目。GNU系统典型地以Linux为内核,合起来就是GNU/Linux系统,GNU/Linux系统有很多的发行版本,比如优麒麟(Ubuntu Kylin)、Ubuntu、CentOS、Debian等等。这些发行版本在桌面系统、软件管理、预装的软件等方面会存在差异,然而基本的命令是一致的,符合标准的软件在各个发 行版都能安装。手机的Android系统的也是以Linux为内核,但不是GNU/Linux系统。

入行生物信息学免不了要学习和使用GNU/Linux系统,因为(包括但不限于):

  1. 大多数生物信息或计算生物学软件仅为运行于Linux而开发。
    1. Linux是自由、免费、开源的,这样方便大家的共同开发、使用、修改;
    2. Linux丰富的命令行工具能够方便地对分析进行个性化;
    3. Linux系统运行稳定、多个用户可以在同一时间内登录同一个系统执行各自多任务而互不影响,适合用于服务器,因此被很多高性能(HPC)计算所选择,生物信息学分析面对大数据,很多分析流程都部署在服务器上,使用者远程登录使用。
  2. 上述这些软件中的绝大多数只能通过命令行调用。
    1. 命令行使用起来很高效而且灵活,更加适合于前沿研究;
    2. 这些软件多数是开源、免费的,而开发图形界面成本会比较高,而研究前沿发展很快,很多软件在不断的发展,开发图形界面不合算。

很多人学习Linux是从远程登录服务器开始的,并不需要自己安装一个Linux系统。这时候并没有系统管理权限,一般只能对自己的目录下的文件进行操作。

如果没有可用的服务器或者想要体验系统管理,而自己的电脑又不是Linux系统,可以安个虚拟机(比如VirtualBox),然后在虚拟机里安装个Linux系统(比如优麒麟)。对于初学者,安装按照默认的设置进行即可。在VirtualBox安装直接使用虚拟光盘加载iso文件即可。而如果自己有台闲置的电脑用来安装Linux系统,可以使用Rufus制作启动U盘。其它安装事项自行上网搜索之。

Shell简介

shell是什么

Linux系统的结构可以简要示意如右/上图,现在的发行版本一般都带有桌面系统,也就是图形界面。而我们平时使用Linux系统主要以命令行为主,这个就是通过Shell将命令传译给系统执行的。远程SSH (Secure Shell)协议登录系统,默认就是打开了shell的,能够看到命令提示符(默认一般用户为$,root用户为#)。在命令提示符后边输入命令,输入完成后,按回车键(Enter或return)就能看到运行的结果或者反馈了。
而如果是登录了桌面系统,可以打开终端(terminal),终端里默认运行shell。

当出现提示符>时,说明命令还没有输入完成,一些固定的搭配只输入了一部分时就会出现这个提示符,比如只输入了半个引号就按了回车,在后半个引号输入前始终会出现提示符>。

shell有sh、bash、dash、wish等等的。Bash (GNU Bourne-Again Shell) 是sh(Bourne Shell)的改进版本,是最常用的一种shell,大多数Linux发行版默认的shell就是bash。查看当前系统中的shell类型用如下命令:

echo $SHELL             # 查看当前用户的shell,但并不一定是正在用的
ps -p $$                # 查看当前正在用的shell,默认是bash
echo $0                 # 查看当前正在用的shell
sh                      # 换成使用sh
ps -p $$                # 可以看到当前正在用的shell已经变了,但echo $SHELL 还没有变
exit                    # 退出上边的sh,回到bash

想要知道系统里安装了哪些shell,可以用如下命令查看:

cat /etc/shells

shell命令

shell本身也是一个运行程序,在shell中输入的命令可以包含选项和参数,这些选项和参数都有默认的值,不在命令中指明的时候就是默认的值。命令有三种类型(可用用type查看):

  1. 内置命令:shell内建(builtin)的命令,比如echo
    type echo                                
    ##  echo is a shell builtin
    #这里或者得到:echo 是 shell 内建
  2. 外部命令:shell调用的其它程序,也就是可执行文件,其名称用作命令,比如date。外部命令用过一次之后将被录入哈希表,这样下次调用的时候先从哈希表里找,寻找更高效。
    type date                                
    ##  date is /usr/bin/date
    #这里或者返回: date is hashed (/usr/bin/date)
  3. 别名(alias):命令包含选项和参数,带上选项和参数的命令可能比较长,为了输入简便,可以取了别名,比如,试试如下命令:
    # 先设置alias,这样用la就等于用后边的一串:
    alias la='ls -l -a -h --color=auto'
     
    la /lib*
    ##  lrwxrwxrwx. 1 root root 7 6月  22 2021 /lib -> usr/lib
    ##  lrwxrwxrwx. 1 root root 9 6月  22 2021 /lib64 -> usr/lib64
     
    which la
    ##  alias la='ls -l -a -h --color=auto'
    ##          /usr/bin/ls
     
    type la
    ##  la 是 `ls -l -a -h --color=auto' 的别名
     
    unalias la
    la
    ##  bash: la: 未找到命令...

shell支持编程,是一种脚本语言,支持基本的编程元素,这样就能够方便地对命令进行批量化调用。

命令规范

shell命令是区分大小写的,不要弄错大小写。另外,计算机语言是非常严格的,输入命令时需要非常仔细,任何不完全一致都可能导致无法运行或者弄错成别的命令而得到不同的结果甚至可能会导致严重的后果。注意空格,作为一个整体的字符串如果含有空格,需要整个字符串用引号引起来。

自动补齐

输入命令的部分字符后,可以按Tab键,剩下的如果只有一个选择,那么就会自动补齐。 如果后边待补充的有多个选择,那么按一次Tab键没有补齐,再按一次就会把所有的所有的选择打印在屏幕上。比如,输入cd /ho,按一次Tab键,就会自动补齐为cd /home/。比如,输入cd /b,按一次Tab无反应,再按一次,就出现了bin/ boot/两个选项。
因此在使用的时候,如果按一次Tab没有补齐,那么可以再输入一些字符,使得剩下的部分变得唯一,再按一次Tab这样得到补齐。这样就能节约大量的命令输入时间。

命令历史

history  | less           # history命令显示所有你已经输入过的命令,管道传给less以免刷屏。
                          # less 用来查看文本内容,按向上或向下箭头来实现滚动。按q退出。

寻求帮助

--help选项

对于标准的Linux命令,可以在命令后加上–help选项来查看简短的帮助信息,查看命令的用法,以及可选的参数和选项,比如:

wc   --help          # 查看 wc 命令的简要帮助信息
date --help | less   # 查看 date 命令的帮助信息,通过管道 | 传给 less 这样避免帮助信息过多时刷屏,查看完成后按 q 退出

man命令

对于Linux自带的命令,可以用man命令查看其使用手册,比如:

man wc              # 查看 wc 的使用手册,这包含非常详尽的信息,包括 NAME、SYNOPSIS、DESCRIPTION、AUTHOR、等等的信息
man cp              # 查看 cp 的使用手册,其余仿此,man 后边加上查看的命令即可
man man  | less     # man 自己的手册

上网搜索

当不知道用什么命令或者某个命令怎么用的时候,可以上网搜索,可以先搜索一下本页面。

用户管理

更改密码用命令passwd,查看当前用户名用whoami,查看系统的主机名用hostname:

passwd            # 后边不加任何参数,默认修改自己密码,根据提示输入当前密码,然后再输入两次新密码即可
 
whoami            # 查看自己的用户名,等同于 echo $USER
hostname          # 查看系统的主机名,等同于 echo $HOSTNAME
who               # 查看当前有谁在线

如果自己有root权限,则可以增加用户,和给用户设置密码:

sudo su                          # 先使自己变成root身份,不再需要root身份了则使用exit命令退出
adduser xxxxx                    # 创建一个叫xxxxx的用户
passwd  xxxxx                    # 设定或修改用户xxxxx的密码,同样根据提示输入两次密码即可
 
hostname yyyyy                   # 将hostname临时修改为yyyyy,这只是修改了临时主机名(transient hostname),重启中断则复原
hostnamectl set-hostname yyyyy   # 将hostname修改为yyyyy,这更改了/etc/hostname文件中的静态主机名(static hostname)

系统信息

当发现系统运行慢了时候,就需要查看一下系统的资源使用情况。可以通过lscpu命令查看系统CPU的信息,free查看总内存和内存使用情况,df命令查看硬盘情况,用top可以查看CPU、内存的使用情况以及进程的资源占用情况。

lscpu

lscpu                                  # 看到CPU的详细情况,第四行就是CPU的数量
echo "$(lscpu -e | wc -l) -1" | bc     # 这样直接得到的就是CPU的个数,-e指示以列表可读形式展示信息,每个线程一行

free

free -h -w                              # 查看内存的情况,-h指示方便人查看的单位但,-w指示将buffers和cache分开展示

total是总的内存,used是实际已使用,free为未使用,available指可调用的,;对于行:Mem内存,Swap是交换分区。

df

df -h                                  # 查看硬盘的情况,-h指示方便人查看的单位但是

top

top                                    

输出示例如下(……表示被删掉的若干行):

top - 11:21:18 up 66 days, 11:15,  1 user,  load average: 46.91, 25.09, 19.18
Tasks: 752 total,   7 running, 745 sleeping,   0 stopped,   0 zombie
%Cpu(s): 74.6 us,  0.1 sy,  0.0 ni, 25.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
MiB Mem : 128283.7 total,  54315.1 free,   3304.6 used,  70664.0 buff/cache
MiB Swap:   4096.0 total,   4086.0 free,     10.0 used. 123905.4 avail Mem
 
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1015735 whcbg     20   0  596252 299048   3824 R 798.0   0.2  29:00.46 raxml-ng
……
1015814 whcbg     20   0   65428   5576   4076 R   1.0   0.0   0:01.38 top
……

这里需要关注的是load average,其值应该要小于CPU的数目,超过总的线程数则过载了,系统会变慢。后边的三个数字依次是过去1分钟、5分钟、15分钟内的平均值。%CPU是指该进程CPU的使用百分比,应该接近预计使用的线程数。
top的结果默认每3秒钟就更新一次,按q退出。按1则展示每个CPU的使用情况,再按一次1则返回;

目录与文件

目录实际上就是文件夹,Linux系统的目录从根目录(/)开始,一级一级的目录之间用/分隔,比如/usr/bin就表示根文件夹里的usr文件夹里的bin文件夹,而/usr/bin/cd就表示这个文件夹里的cd文件。/usr/bin和/usr/bin/cd就是指向这个bin文件夹和cd文件的路径。像这样,从根目录出发的,就叫绝对路径。
工作目录就是当前当前所处的目录,也就是当前所默认的目录,就是命令没有额外指定则用此目录。从当前的目录出发,走别的别的路径,就称为相对路径。相对路径中用.表示当前目录,二用..表示上一级目录。 比如/usr/bin/../..就指向了根目录,而/usr/bin/./.就还依然指向bin文件。

查看与切换工作目录

pwd              # Print Working Directory,打印工作目录的绝对路径
cd               # Change Directory,切换工作目录,后边不加参数的时候,默认是切换到用户的HOME目录,一般为 /home/username
cd ~             # ~ 表示HOME目录 
cd /             # 切换到根目录,用 pwd 看看切换到了哪里
cd usr/bin       # 切换到usr文件夹里的bin文件夹,这里usr在/里,相对于/出发,可以这样等同于 ./usr/bin,用 pwd 看看切换到了哪里
cd ../..         # 相对于上一步usr/bin 目录,上一级再上一级,又回到了/,用 pwd 看看切换到了哪里
ls               # 查看当前工作目录下的文件及文件夹
ls -l -h -a      # 可以加上参数,-l 指示以较长格式列出信息,
                 # -h 指示以方便人类识别的方式列出文件大学,也就是使用M、G等单位,而不是一个非常巨大的以b为单位的数字, 
                 # -a 表示列出所有的文件,包括隐藏文件。 Linux中以''.''开头的文件或文件夹默认是隐藏的,比如~/.ssh
ls -lha          # 多三个选项可以合并在一起写

ls -lha命令得到的结果示例如下:

drwxrwxr-x. 4 whcbg whcbg 167 8月   3 22:34 .
drwxrwxr-x. 3 whcbg whcbg  16 8月   3 17:24 ..
-rw-rw-r--. 1 whcbg whcbg   0 8月   3 21:20 file1.txt
-rw-rw-r--. 1 whcbg whcbg  22 8月   3 21:20 file2.txt
drwxrwxr-x. 3 whcbg whcbg  16 8月   3 21:20 dir1
drwxrwxr-x. 2 whcbg whcbg   6 8月   3 21:20 dir2

可以看到,结果分为9列:第1列(如drwxrwxr-x.)表示文件类型和权限,第一个字母d代表文件夹,-代表常规文件,l表示是软连接,c表示字符文件,接下来的三组三字符依次代表所属用户、所属组、其它用户的权限,r、w、x代表具有读、写、执行的权限,相应的位置为-则代表无此权限;第2列表示文件的连接数或文件夹的子目录数;第3列表示文件所所属用户;第4列表示文件所属的组;第5列表示文件的大小,默认单位是字节;第6~8列默认表示最后被修改的时间;第9列(最后一列)是文件名,其中.表示当前目录,..表示上一级目录。

创建目录

cd                                          # 先切换到自己HOME目录,别的目录自己可能没有写的权限
mkdir whlab                                 # MaKe DIRectory,在当前工作目录下创建一个叫 whlab 的文件夹
mkdir -p whlab/XS/XS01                      # 当创建的文件夹的上一级不存在时,需要加上 -p 选项
mkdir -p ~/whlab/XS/{XS02,XS03,XS04,XS05}   # 同时创建XS02、XS03、XS04、XS05四个文件夹
ls ~/whlab/XS                               # 能够看到已经创建了的文件夹

创建文件

文件通常是根据各个软件的输出设定文件名,然后输出就写到文件里。创建文件可以使用touch命令,可以使用>符将将输出到屏幕的内容定向到文件,文件不存在则会创建一个文件,如果存在则会覆盖已存在的文件,因此要小心。 »是将内容附加在文件内容的后边。 2>和2»表示将执行的错误输出结果重定向到文件。&»表示将标准输出和错误输出都写到指定的文件。

touch  ~/whlab/XS/file1.txt                          # 目前不存在此file1.txt文件,则生成一个叫file1.txt的文件
echo "Something interesting" > ~/whlab/XS/file2.txt  # 也是生成一个file2.text的文件
ls -l -c ~/whlab/XS/                                 # 可以看到,touch生成了文件file1.txt是0, ls后边用 -c 表示查看最近的改变时间
touch ~/whlab/XS/file2.txt                           # 当文件存在的时候,touch会改变这个文件的时间戳
ls -l -c ~/whlab/XS/                                 # 可以看到,时间戳改变了
stat  ~/whlab/XS/file2.txt                           # stat命令用于查看文件状态,包括全部的时间戳
cat ~/whlab/XS/file2.txt                             # 查看文件的内容,注意,比较大文件要避免用这个命令,太多内容显示在屏幕上不变观察,甚至可能耗费很多的时间
less ~/whlab/XS/file2.txt                            # 比较大的文件用less查看更合适

文件与目录操作

rm用于删除文件和文件夹,mv用来移动或者重命名文件和文件夹,cp用来复制文件或文件夹的。cp 和 mv 具有如果目标出现相同文件名的文件的时候,会提示是否覆盖,如果确定可以覆盖,可以加上-f选项,这样样将会强制覆盖。使用-f选项要小心。 rm也有-f选项,将会强制删除,不再提示是否删除。需要非常小心。使用rm -rf *这个命令前一定要三思,这个命令会将工作目录下的所有文件夹和文件都删除,加上 -i 也不提示。

cd  ~/whlab/XS/                     # 先切换工作目录,此目录为上文所建
ls                                  # 能够看到已经创建了的文件夹
rm file1.txt                        # 删除文件file1.txt
rm -r XS05                          # rm 用于删除文件和文件夹,删除文件夹的时候加 -r 选项
ls -R ..                            # ls 加上 -R 参数能够递归列出文件夹里的文件夹里的类容,直到最后一级
 
mv file2.txt file3.txt              # 将文件名file2.txt重命名为file3.txt
mv XS02 XS06                        # 将文件夹XS02重命名为XS06。
mv ~/whlab/XS/XS03 ~/whlab/XS/XS04  # 将文件夹XS03 移动到XS04里,可以使用绝对路径或相对路径指向文件
ls -R ~/whlab/XS                    # 看看上两步移动及重命名之后的
 
cp file3.txt file4.txt              # 复制文件
cp -r XS04  XS06                    # 复制文件夹需要加上 -r 参数  

cat可用来将纯文本文件的内容输出到屏幕,使用转向可以将一个文件的内容复制到另一个文件。可以用head、tail、less等命令查看文件部分或全部的内容,可以使用wc统计文件的行数、单词数、字节数。

echo -e '1\ta\n2\tb\n3\tc\n4\td\n5\te\n6\tf\n7\tg\n8\th\n9\ti\n10\tj\n11\tk\n12\tl' > test1.tsv   # 先创建两个文件
echo -e '1\tA\n2\tB\n3\tC\n4\tD\n5\tE\n6\tF\n7\tG\n8\tH\n9\tI\n10\tJ\n11\tK\n12\tL' > test2.tsv   
 
less test1.tsv             # 查看文件的内容,按q退出
less test2.tsv
 
cat test1.tsv > test.tsv   # > 为重定向,把输到stdout (屏幕)上的重定向到文件
less test.tsv
 
cat test2.tsv > test.tsv   # 原来文件将被覆盖
less test.tsv
 
cat test1.tsv > test.tsv   # > 为重定向,把输到stdout (屏幕)上的重定向到文件
cat test2.tsv >> test.tsv  # >> 为将内容追加到文件末尾
less test.tsv
 
cat test1.tsv test2.tsv test1.tsv test2.tsv test1.tsv test2.tsv > Test.tsv  # 可以吧多个文件cat到一个文件
 
head test.tsv              # 查看前边几行,自己数是几行,可以使用 -n 参数指定显示行数,比如  head -n 1 test.tsv
tail test.tsv              # 查看末尾几行,自己数是几行,可以使用 -n 参数指定显示行数,比如  tail -n 1 test.tsv
wc -l test.tsv             # 统计行数

文件的权限

通过chown命令来改变文件和文件夹的所属用户和组,通过chmod命令来设置文件和文件夹的权限。文件具有可读(r)、可写(w)、可执行(x)权限可以依次用数字4、2、1来表示,无相应权限用0表示,数字加得到单独一个数字即可表示各种权限的组合。比如7表示可写可读且可执行。这样三个权限可以用三个数字依次表示,比如777则表示对所有人都开放全部权限。

echo "Hi WhLab" > test.txt  # 产生一个示例文件
ls -l test.txt              # 初始的是 rw-r--r--
 
chmod =x test.txt           # 将user、group、other的权限都设成x, 体会等号的用法
ls -l test.txt    
 
chmod u=w test.txt          # 将user的权限都设成w, u表示user,同样g表示group,o表示other
ls -l test.txt 
 
chmod u+r test.txt          # 将user的权限增加r, 体会+的作用
ls -l test.txt    
 
chmod o-x test.txt          # 将other的权限减少x,体会-的作用
ls -l test.txt    
 
chmod 111 test.txt          # 将user、group、other的权限都设成x;可以用数字代表权限
ls -l test.txt     
cat test.txt                # 不可读了
echo "Hi Hong" > test.txt   # 不可写了
 
chmod 222 test.txt          # 将user、group、other的权限都设成w
ls -l test.txt    
cat test.txt                # 不可读
echo "Hi Hong" >> test.txt  # 可写
 
 
chmod 444 test.txt          # 将user、group、other的权限都设成r
ls -l test.txt    
cat test.txt                #可读
echo "Hi Hong" >> test.txt  #不可写
 
chmod 731 test.txt          # 将user、group、other的权限分别设成rwx、-wx、--x
ls -l test.txt    
 
mkdir -p test1/test2
chmod 111 test1
ls -l 
ls -l test1                 # 没有权限了
 
chmod 777 test1             # 最宽松权限,要慎重使用
ls -l 
ls -l test1                 # 看看 test1里的文件夹test2并没有跟着变化
 
chmod -R 775 test1          #  -R 实现递归,就是文件夹中的文件已经文件夹都会跟着改变,直到最底层
ls -l 
ls -l test1                 # 看看 test1里的文件夹test2 跟着变化了

硬链接与软连接

数据在硬盘里的存储单元就是文件,文件都有文件名和数据。数据包括用户数据(user data) + 元数据 (metadata)。 用户数据就是文件的真实内容,元数据为文件的附加属性,文件大小、创建时间、所有者等信息。元数据中的索引节点(inode)号才是文件的唯一标识。为了方便文件的共享,Linux中引入了软连接和硬链接两种,硬链接是指具有相同inode号的文件,而软链接则是指向另一个文件的特殊文件,其特殊性在于,当你对软连接文件进行一些操作时,实际上是对指向的文件进行操作。这样当删掉硬链接中的某一个时,对另一个没有影响,而删除了软连接的源文件之后,这个软连接就成了死链接。 不能对文件夹创建硬链接。

rm test1.txt test2.txt test3.txt                  # 如果这些文件存在,先删除了,如果不存在,报错也无所谓,
touch test1.txt
stat test1.txt                                    # stat 命令查看文件的附加属性,包括文件名, inode号等等的。
ls -i test1.txt                                   # -i 能够同时展示inode号
ls -li test1.txt                                  # 增加的第一列是inode号
 
ln test1.txt test2.txt                            # 对test1.txt创建一个硬链接叫test2.txt
ls -li                                            # inode号同
 
ln -s test1.txt test3.txt                         # 加-s后,对test1.txt创建一个软链接叫test3.txt
ls -li                                            # inode号不同
 
ln -s `pwd`/test1.txt test4.txt
ls -li                                            # 看一下使用绝对路径的情况
 
stat test1.txt test2.txt test3.txt test4.txt      # 硬链接除了文件名以外,其它的信息都是相同的,软连接则是一个新的文件
 
mkdir test1                                       # 如果上文已经创建,这里报错是正常的
 
mv test2.txt  test1
mv test3.txt  test1
mv test4.txt  test1
 
cd test1
ls -li                                            # 可以看到test3.txt变成了死链接,因此制作软连接的时候,最好使用绝对路径
stat ../test1.txt test2.txt test3.txt test4.txt  
 
rm ../test1.txt
ls -li                                            # 删除源文件之后,软连接变成了死链接

标准输入(stdin)、标准输出(stdout)与标准错误(stderr)

正常情况下,一个Linux命令开始执行时会有三个数据流为之打开,一个用于输入,一个用于输出,一个用于诊断或者报错消息。通常情况下,这三个数据流都指向终端,用户通过键盘输入,而输出信息也打印都屏幕上。但也会根据父进程而设定成文件或者别的设备。这三个数据流依次被称为标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。数据流就是数据传输的通道,程序运行时从输入流读取数据,运行正常输出的结果就传送到输出流,而如果发生错误的信息或者警告等信息则会传送到输出流。

管道

很多linux的命令输出直接达到屏幕上,也就是输出到stdout,这些输出可以直接作为一些命令的输入,也就是stdin。 这时候中间用 | 链接,也就是管道。

echo -e '1\ta\n2\tb\n3\tc\n4\td\n5\te\n6\tf\n7\tg\n8\th\n9\ti\n10\tj\n11\tk\n12\tl' > test1.tsv 
echo -e '1\tA\n2\tB\n3\tC\n4\tD\n5\tE\n6\tF\n7\tG\n8\tH\n9\tI\n10\tJ\n11\tK\n12\tL' > test2.tsv
 
cat test1.tsv test2.tsv | less
 
cat test1.tsv test2.tsv | wc -l    #统计总行数
wc -l test1.tsv test2.tsv 
 
cat test1.tsv test2.tsv | wc -c
 
ls -l | less

文件下载

文件下来常用的命令有wget和curl。wget能够递归地下载,而且连接不成功的时候会不断重试。curl功能更强大,支持更多的协议。wget快速大多数场合下实用curl更适合。

wget ftp://ftp.biolab.wang/test.txt               # wget后边直接跟文件的链接,默认下载下来到当前工作目录,文件名保持不变
cat test.tx                                       # 看看文件内容
 
curl ftp://ftp.biolab.wang/test.txt               # 可以看到,不加任何参数的时候,这个文件的内容被输出到屏幕
 
 
wget -O Atest.txt ftp://ftp.biolab.wang/test.txt  # -O中的O为大写,指定后,下载到文件重命名为Atest.txt
curl -o Btest.txt ftp://ftp.biolab.wang/test.txt  # -o中的o为小写,指定后,下载到文件命名为 Atest.txt
 
wget Atest.txt ftp://ftp.biolab.wang              # 链接不指向文件时,没下载任何内容
curl Btest.txt ftp://ftp.biolab.wang              # 链接不指向文件时,列出目录下的文件

wget 的递归下载功能能够把整个网站都下载下来

wget --mirror -p --convert-links -P biolab ftp://ftp.biolab.wang/  # 将整个网站都下载下来了

文件完整性检测

当下载文件比较大的时候,往往需要检测下载是否完整以及下载过程中是否出错,这时候需要用到md5sum命令检验。通常在给别人提供比较大的文件的时候,需要同时提供一个文件记录md5sum值。比如这里有个文件叫 test.txt

[ -f test1.txt ] || echo "This is a file for MD5 check!"  > test1.txt  # 如果不存在则创建一个test.txt文件
[ -f test2.txt ] || echo "This is A file for MD5 check!"  > test2.txt  # 如果不存在则创建一个test.txt文件

使用md5sum能够得到MD5值

md5sum test1.txt   test2.txt               # 如果有更多的文件则空格隔开列在后边即可

得到的执行这个命令可以得到如下的结果,输出到屏幕,可以看到,两个文件只有很小的区别,MD5值差别巨大

a2963ac24fdd007372671c9e8be4bfe7 *test1.txt
f2ce3b28efeea7aeeed8c2e76db18579 *test2.txt

这个结果可以写入到文件,用于校验

md5sum test1.txt  test2.txt > test.md5      # 文件为两列,第一列是MD5值,第二列为对应的文件

使用–check选项,则根据MD5值记录文件校验文件,

md5sum --check test.md5                     # 如果文件的MD5值与记录一致,则会输出为OK
md5sum --check --quiet test.md5             # 加上 --quiet 校验通过的不再一一列出  
sed -i s/This/ThiS/    test1.txt            # 稍微修改一些test1.txt文件
md5sum --check --quiet test.md5             # 加上 --quiet 校验通过的不再一一列出,检验失败的会标记FAILED  

压缩与解压缩

先准备一下学习环境,建个文件夹,创建几个测试文件,对这些命令可以先不用弄懂为啥是这样,等都学完了就懂了。

[ -f ~/whlab/XS/XS01 ] || mkdir -p ~/whlab/XS/XS01     # 如果不存在这个文件夹则创建一个
cd ~/whlab/XS/XS01                                     # 切换到这个文件夹,先做一些准备
for i in 1 2 3 4 5 6; do echo $i > file${i}.txt; done  # 先产生6个测试文件,内容为1-6
ls -l                                                       

gz

gzip   file1.txt                                       # 压缩file1.txt为gz格式,生成文件file1.txt.gz
ls -l                                                  # 默认情况下gzip压缩会删除原文件,可以使用 -k 参数保留源文件
 
gunzip file1.txt.gz                                    # 解压缩test.tsv.gz
ls -l                                                  # 默认情况下gunzip解压缩会删除原文件,可以使用 -k 参数保留源文件
 
gzip -k file2.txt file3.txt file4.txt file5.txt        # 多个文件作为参数的时候是分别被压缩的。同样gunzip对多个文件也是分别解压
 
gunzip -c file*.txt.gz > file6.txt                     # 可以加 -c 参数把结果写到标准输出,重定向到文件,这样可以重命名文件
gzip   -c file6.txt    > file6.txt.gz                  
 
cat file6.txt.gz                                       # 可以看到,压缩之后就不再能够用cat了
zcat file6.txt.gz                                      # 这时候需要用zcat,等同于 gunzip -c 
zcat file6.txt.gz | less                               # 如果文件比较大,用管道传给less

tar.gz/tar.bz2/tar.xz/tar.Z/等等

使用tar对文件和文件夹实现打包和解包,加上相应的参数同时可以压缩和解压:-c指示创建压缩文件;-x指示解压文件; -v指示将处理的文件列出来;-f后边接压缩包文件名,指示待解压的文件或者压缩包的文件名;-z指示通过gzip压缩,文件拓展名为tar.gz或者tgz;-j指示通过bzip2压缩,文件拓展名为tar.bz2;-J指示通过xz压缩,文件拓展名为tar.xz;-Z指示通过compress压缩,文件拓展名为tar.Z;另外还有更多的压缩方式可供选择,不常用,很少遇到,感兴趣可以使用man tar查看之。

tar -cvf  files.tar     file1.txt file2.txt file3.txt   # 将几个文件打包到一起,没有压缩选项,生成的文件的名称紧接在 -f 后
tar -czvf files.tar.gz  file1.txt file2.txt file3.txt   # 打包并通过gzip压缩
                                                        # 待打包和压缩的文件和文件夹放在后边,空格隔开
ls -l                                                   # 可以看到,压缩后文件更小
tar -cjvf files.tar.bz2 file1.txt file2.txt file3.txt   # 打包并通过bzip2压缩
tar -cJvf files.tar.xz  file1.txt file2.txt file3.txt   # 打包并通过xz压缩
tar -cZvf files.tar.Z   file1.txt file2.txt file3.txt   # 打包并通过compress压缩
 
less files.tar.gz                                       # 查看压缩包里的内容
 
tar -xzvf files.tar.gz                                  # 解压tar.gz文件
tar -xjvf files.tar.bz2                                 # 解压tar.bz2文件,则把xzvf换成xjvf,其余仿此
tar -xJvf files.tar.xz  
tar -xZvf files.tar.Z  
 
tar -czvf all.tar.gz  ~/whlab/XS/XS01                   # 对文件夹进行打包,仔细看展示在屏幕上的信息
less all.tar.gz                                         # 查看一下压缩包里的内容,可以看到,路劲也被压缩进去了
tar -xzvf all.tar.gz                                    # 解压缩
ls -l -R                                                # 看看,解压缩之后还保留了路径,但是从相对于/变成了相对于当前文件夹

zip与jar

通过zip和unzip压缩和解压缩zip文件。zip的选项常用的有:-r指示递归地遍历整个目录结构,当压缩对象中含有文件夹时需要加上这个参数,不然仅仅只是包括了文件夹而不包括文件夹里边的文件和文件夹;-q指示不把压缩过程打印到屏幕上;-e指示给压缩包添加密码;还有其它很多的选项,可以用man zip查看。

cd /home/whong/whlab/XS
 
zip ZIP01.zip XS01                            # 将文件夹XS01添加到压缩文件 XS01.zip
less ZIP01.zip                                # 可以看到,XS01里的文件和文件夹并没有被添加
 
zip -r ZIP02.zip XS01                         # 将文件夹XS01及其里边的内容添加到压缩文件 XS01.zip
less ZIP02.zip                                # 可以看到,XS01里的文件和文件夹也被添加
 
zip -r ZIP03.zip /home/whong/whlab/XS/XS01    # 包括了路径,从home开始,解压出来的文件夹是从home开始
less ZIP03.zip                                # 看看文件的路径             
 
unzip ZIP03.zip                               # 解压得到home文件夹
ls -l -R   home                               # 看看home文件夹里有啥                 
 
zip -r ZIP04.zip  XS01 XS02 file1.txt         # 可以把文件夹和文件夹一起压缩
zip -9 -r ZIP05.zip  XS01 XS02 file1.txt      # -9设定压缩水平,可以是0~9,默认是-6,压缩水平越高,消耗计算资源越多,需要更多的时间
zip -r ZIP05.zip *                            # 把当前目录的所有非隐藏文件都打包到,要包括隐藏文件还要加上 .*

jar文件本质上实际上是zip,可以用unzip来解压缩。当然可以用jar命令来压缩和解压缩,jar命令用法和tar相似:-c指示创建;-x指示解压;-v指示将过程打印到屏幕;-f指定压缩文件的名称。

cd /home/whong/whlab/XS
jar -cvf JAR01.jar XS01 file1.txt file2.txt   # 压缩得到jar文件
less JAR01.jar                                # 可以看到,自动添加了META-INF/MANIFEST.MF文件夹
jar -xvf JAR01.jar                            # 解压jar文件
unzip    JAR01.jar                            # 可以用unzip来解压

文本处理

文本处理常用的命令有vi、cat、grep、cut、sort、uniq、sed、awk等等的命令

vi

vi是比较常用方便的编辑器,现在使用vi大都实际上是使用vim,vim可以视为vi的升级版本,可以用which vi查看一下系统里的vi是不是vim的别名。比如要更改或者新建文件test.txt,用如下界面就进入编辑界面:

vi test.txt       # test.txt 改成你想要的文件名

初进入是命令模式。按键盘上的'' i'' 进入输入模式,这样就能往文件里输入内容了;可以输入或者粘贴。方向键控制光标所在的位置,退格键可以逐个删除。从编辑模式进入名模式按退出ESC键,然后输入命名进行保存,退出等。:w为保存,:q为退出,:wq 为 保存并退出,:q!为强制退出,不保存。
命名模式下:按两次d删除整行; :n命令跳到第n行;,:$ 跳到最后一行;;/pattern为向下查找,pattern是要找的内容的表达式;?pattern 为向上查找 :set number 显示行号; :set nonumber 不显示行号。

cat

#用如下一行命令先创建一个2列12行的文件,看不懂这一行命令没有关系,先不要纠结
echo -e '1\ta\n2\tb\n3\tc\n4\td\n5\te\n6\tf\n7\tg\n8\th\n9\ti\n10\tj\n11\tk\n12\tl' > test1.tsv  
echo -e '1\tA\n2\tB\n3\tC\n4\tD\n5\tE\n6\tF\n7\tG\n8\tH\n9\tI\n10\tJ\n11\tK\n12\tL' > test2.tsv  
 
cat test1.tsv   #查看文件的所有内容,不要用于大文件,不然可能会很卡
 
cat test1.tsv > test.tsv # > 为重定向,把输到stdout (屏幕)上的重定向到文件
cat test.tsv
cat test2.tsv > test.tsv #原来文件将被覆盖
cat test.tsv
 
cat test1.tsv > test.tsv # > 为重定向,把输到stdout (屏幕)上的重定向到文件
cat test.tsv
cat test2.tsv >> test.tsv # >> 为将内容追加到文件末尾
cat test.tsv
 
cat test1.tsv test2.tsv test1.tsv test2.tsv test1.tsv test2.tsv > test.tsv  #多个文件合并为一个文件

grep

grep (global regular expression printer) 是一个非常常用的命令。逐行对文件进行指定模式的搜索。

echo -e 'ACT TAG AGG TAG\nATG TTT\nAAA GGG\nCCC\nATG' > input.txt  #示例文件
cat input.txt
 
grep ATG input.txt      # 返回包含ATG的行
 
grep -c ATG input.txt   # 返回包含ATG的行的总行数
 
grep ^C input.txt       # ^表示开头
 
grep T$ input.txt       # $表示结尾
 
ls -l | grep ^d   # 列出所有文件夹

cut

sort

根据特定的列对文件进行排序.

echo -e 'chr1\t1\t100\nchr2\t4\t10\nchr1\t4\t10\nchr3\t3\t40' > test1.bed
 
sort test1.bed                  # 不分列
sort -k2 test1.bed              # 按照第2列排序
sort -k2n test1.bed             # 按照第2列排序,但当做数字
sort -k2,2n test1.bed           # 这和上一条也是一样的,根据第2列到第2列排序。 -km,n 根据第m到第n列排序
sort -k1 test1.bed              # 按照第1列排序 
sort -k1,1 -k2,2n test1.bed     # 先按第一列排,再按第二列排 
sort -k2,2n -k1,1 test1.bed     # 按照第二排序,再按第一列排

uniq

uniq总是要接着sort使用,因为它只会对相邻的元素判断是否重复。

echo -e 'chr1\nchr2\nchr1\nchr3\nchr4\nchr1\nchr5\nchr2\nchr6\nchr3' > test1.txt
cat test1.txt
uniq test1.txt
sort test1.txt | uniq            # 看看sort之后uniq的效果
cat test1.txt  | uniq      
cat test1.txt  | sort | uniq     
sort test1.txt | uniq -c         # -c统计各元素的重复次数

sed

sed (stream editor)用来对输入文件或者数据流进行编辑,逐行进行编辑,sed没有交互模式。通常我们用来做替换。

echo -e 'ACT TAG AGG TAG\n TTT\nAAA GGG\nCCC\nATG' > input.txt  #产生一个示例文件
cat input.txt  #查看一下文件
 
sed '' input.txt  # 不加指令的时候会把每一行输出来
 
sed -n '' input.txt  # -n 表示安静地进行,告诉它做什么,它才做,这里就是抑制了默认的情况
 
sed -n 'p' input.txt  # p 表示打印
 
sed 's/TAG/!STOP!/'  input.txt   # s/x/y/ 表示将x替换成为y
 
sed 's/TAG/!STOP!/ g'  input.txt  # g 表示全局之后替换所有的
 
sed 's/T/U/g' input.txt   # 这是一个将DNA序列转成RNA列的例子
 
sed 's/T/U/ 2' input.txt   # 只对第二次出现的模式进行操作
 
sed -n 's/T/U/g' input.txt   # -n  
 
sed -n 's/T/U/gp'  input.txt   # p 
 
sed -e 's/T/U/g' -e 's/A/a/g'  input.txt  #当想使用多个命令的时候,使用 -e, 每个-e后边跟一个命令,可以有很多
 
echo -e "s/T/U/g\ns/A/a/g" > edit.sed  #可以把多条命令放在一个文件中作为脚本使用
cat edit.sed   #看看脚本里的内容
 
sed -f edit.sed  input.txt   #通过-f加脚本文件使用脚本文件中的命令
 
sed -n '3,4 p' input.txt     # m,n 这种中模式是定位用的,这里就是第3到第4行, 动作是p
sed '3,4 p' input.txt        # 看看不加-n的效果,这样可以用来重复一些行
 
sed  '3,4 d' input.txt  # d 表示delete
 
sed -n '/^A/=' input.txt  #返回以A开头的行。 ^表示开头, 而 = 表示行号
 
sed '/^A/=' input.txt  #思考一下不加-n时候的效果  
 
cat input.txt    # 如上的操作原文件未受到影响
 
 
sed 'y/ACGT/acgt/' input.txt   # y/.../.../ 字符转换,字符依次对应
 
sed 'y/ACGT/acg/' input.txt   # 报错
 
sed '/^A/y/ACGT/acgt/' input.txt    #只对以A开头的行进行转换, /^A/
sed '/^A/!y/ACGT/acgt/' input.txt    #不对以A开头的行进行转换,/^A/! ,注意叹号!
 
sed '2,4y/ACGT/acgt/' input.txt    #只对2-4行进行
sed '2,4!y/ACGT/acgt/' input.txt    #不对2-4行进行
 
sed -i 's/T/U/g' input.txt   # 加参数 -i 的时候在原文件上进行编辑
 
cat input.txt
 
 
sed -i '1iAddThisBeforeThe1stLine' input.txt   #在第一行前加入一行
 
cat input.txt
 
sed -i '$iAddThisBeforeTheLastLine' input.txt   #在第最后前加入一行
 
cat input.txt

sed可以用来对字符进行一些替换,比如要sample1.sam 改成sample1.bam可以使用管道,像这样:

echo "sample1.sam" | sed 's/sam/bam/'
 
Var1="sample1.sam"
Var2=`echo "sample1.sam" | sed 's/sam/bam/'`
echo $Var2

这在批量执行某个操作的时候就比较有用了。

awk

AWK是一个编程语言,这里只讲一些简单的用法,更多信息见AWK。 AWK可以和sed一样,可以对文件进行逐行处理。AWK将文本分为多个记录(record)、记录又分为多个字段(field)进行处理。可以自定义记录的分隔符,不局限于逐行处理了。可以把多行当作一个record,每行当作一个field。 $0表示整个record,$1表示当前record的第一个field, $n表示第n个field. NR是当前记录的序号。 知道一些基本的AWK用法,可以顺手的时候提高效率。
AWK的基本语法结构为:
awk '/pattern/ {action}' 输入文件

echo -e '1\ta B\n25\tb c\n3\tfc df\n84\td ok\n15\txye rte\n6\tzf erhyhy\n7\tag hhh\n48\th ADF\n39\ti ERF\n10\tj B\n11\tK OKK\n12\tl BEST' > test.tsv
 
cat test.tsv    #查看一下,第一列和第二列之间制表符分割,第三列和第
 
awk '/a/ {print}' test.tsv      # 包含a的行被print出来
awk '/a/' test.tsv              # 默认的action是print $0
awk '{print $3}' test.tsv       # 默认的域分割符是制表符和空格,不区分此二者
awk '{print }' test.tsv         # print 是默认print $0
awk '/a/ {print $1}' test.tsv      # 包含a的行被print出来
 
awk -v FS="\t" '{print $1}' test.tsv   # 指定FS: Field Separator
awk -v FS="\t" '{print $2}' test.tsv
awk -v FS="\t" '{print $3}' test.tsv
 
awk -v FS="[ ]" '{print $1}' test.tsv  # 以空格作为FS的写法, 注意这里的空格以两个方括号括起来
 
awk -v RS="[ ]" '{print }' test.tsv    # 以空格作为RS:Region Separator的情况,可以看到,逐region print出来的
 
awk -v FS="\t" -v OFS="," '{print $1, $2}' test.tsv   # 指定OFS: Out Field Separator
awk 'BEGIN{FS="\t"; OFS="," } {print $1, $2}' test.tsv   # 另一种指定FS和OFS的方法, 使用BEGIN语句
awk 'BEGIN{FS="\t"; OFS="," } {print $1, $2} END{print "Done"}' test.tsv   # 使用END语句
 
awk -v FS="\t" -v OFS="," '{print $0}' test.tsv   # 理解一下,$0整个打印的时候
 
awk -v FS="\t" -v ORS="," '{print $1, $2}' test.tsv   # 指定ORS: Out Region Separator
 
awk '{if($1 > 20) print}'  test.tsv   # 使用命令
 
awk '$1 > 20'  test.tsv               # 使用模式匹配
 
awk '$1 ~ /e/' test.tsv      # 对第1列进行模式匹配
awk '$2 ~ /e/' test.tsv      # 对第2列进行模式匹配
awk '$3 ~ /e/' test.tsv      # 对第3列进行模式匹配 
 
awk '{if($3~/e/) print}' test.tsv 
awk '$1 > 10 {if($3~/e/) print}' test.tsv 
 
awk '$3~/e/ && $1 > 10' test.tsv       # 体会这两种方式都能实现这种效果
awk '{if($3~/e/ && $1 > 10 ) print}' test.tsv   # 
 
awk '{if(NR%2==0) $1=$1+100; print}' test.tsv   # % 表示求余, NR表示region的序号,NR除以2余0的行都加100
awk '{if(NR%2==0) {print $1+100}; print}' test.tsv   #看看这样的效果
 
awk '$3 ~ /e/ {x++} END{print x}' test.tsv   # 简单的编程,第三列包含e的行数
awk '{if($3 ~ /e/) x++} END{print x}' test.tsv   # 好吧,我觉得记住这种方法就OK了
 
awk '{x+=$1} END{print x}' test.tsv   #求第一列的和
 
#思考一下,怎么求,所有含有e的行的第一列的和?
 
 
awk 'BEGIN{print 10%3}'   #可以这样来试一些代码,后边不用跟文件
awk 'BEGIN{if("A">"a") {print "Yes" }else{ print "No"}}'
awk 'BEGIN{if(100>10) {print "Yes" }else{ print "No"}}'
awk 'BEGIN{print 100/3}'
awk 'BEGIN{print int(100/3)}'   #AWK里没有整除,可以这样实现整除
awk 'BEGIN{printf("%0.6f\n", 10.63)}'  # %s 表示字符串;%i表示整数;%e表示科学计数;%f为浮点数,%g选择浮点数和科学计数中占空间更少的
awk 'BEGIN{printf("%.2f\n", 10.639876)}'   #控制输出的样式
awk 'BEGIN{printf("%s: %.2f and %g \n", "The numbers are", 10.639876, 0.000000123)}'  
awk 'BEGIN{printf("%s: %.2f and %g \n", "The numbers are", 10.639876, 0.123)}'  
 
 
ls -l | awk '$5 > 100'             # awk也可以接受stdin;列出特定大小的文件
ls -l | awk '/.gz$/'               # 列出gz文件

比如现在有一个fasta文件,文件连接如下:

ftp://ftp.biolab.wang/data/Human_hemoglobin_CDS.fasta

Definition Line示例如下:

>lcl|NM_000519.4_cds_NP_000510.1_1 [gene=HBD] [db_xref=CCDS:CCDS31376.1] [protein=hemoglobin subunit delta] [protein_id=NP_000510.1] [location=51..494] [gbkey=CDS]

现在需要把每条序列拆分到单独的文件中,并且定义行仅保留NM_000519.4这样的ID,文件命名为NM_000519.4.fa这样的,用AWK就非常便捷。 命令如下:

awk -v FS="\n" -v RS=">" -v OFS="\n" '{
    sub("_cds.*", "", $1);
    sub(".*\\|", "", $1); 
    print ">"$0 > $1".fa";
} '  Human_hemoglobin_CDS.fasta

不挂断与后台运行

默认情况下,当我们在终端中输入一个命令后,在命令运行期间,将不再能够输入新的命令,而如果命令没有运行完就关闭这个终端,那么命令将不再继续运行。如果想要能够继续输入命令,可以在命令后边加上&把它放到后台去运行。如果希望关闭终端之后命令还继续运行,那么在命令前加上nohup,这时候标准错误和标准输出默认写入nohup.out文件。

echo "date;sleep 60;date" | sh          # 输出当前时间,等待60s,再次输出时间
                                        # 在运行期间不能输入新的命令。
echo "date;sleep 60;date" | sh &        # 后边加上&之后,回车之后能够输入新的命令了。
nohup echo "date;sleep 60;date" | sh    # 可以看到有提示,不再能够输入新的命令,但是关闭终端之后能够继续运行
nohup echo "date;sleep 60;date" | sh &   # 放到后台运行,关闭终端之后不挂断。
nohup echo "date;sleep 60;date" | sh > nohup.log 2>&1 &

这样将标准错误和标准输出都重定向到文件nohup.log中。运行完成后通过cat nohup.log可以看到两个间隔1分钟的时间。

正在运行的命令转到后台运行

如果命令已经正在运行,但耗时比较长,不想再等,可以将它转到后台,步骤如下:

  1. 使用Ctrl+z将它转到后台,但这时候进程也暂停了
  2. 使用jobs命令查看,可以看到前边的那段命令,最前边是中括号里有个数字,也就是作业号
  3. 使用bg 作业号启动命令在后台运行
  4. 使用fg 作业号可以将后台运行的命令放到前台来运行。如果这时候想要放到后台就重复上边的1~3步。

终止正在后台运行的程序

可以通过ps来查到到PID,然后使用kill命令将其终止。比如下边这个命令,找到上边的正在运行的sh进程的PID

ps -u    |  awk '$11=="sh" {print $2}' 

这里要注意,如果得到的PID有多个,那么需要甄别一下哪个是你想要终止的。

kill -9 PID   # 将这里的PID换成上边一步得到的数字

另外也可以将后台的进程先转到前台,然后再用Ctrl+c来将它终止掉。

通配符与正则表达式

通配符主要用于匹配文件名,常用于ls、find、cp、mkdir等命令,使用时不用引号引起来
正则表达式主要用于匹配文件内容中的字符串,常用于命令grep、sed等等命令,使用时要用引号引起来

通配符

通配符 含义 说明
* 匹配0个或者多个任意字符 a*表示以a开头的任意文件;a*.tsv表示开头是a,结尾是.tsv,中间没有字符或者有任意个数的任意字符的文件
? 匹配单个任意字符 a?.tsv表示以a开头,以.tsv结尾的,中间还有一个字符,中间这个字符可以是任意的字符
[] 匹配括号中的字符中的任意一个,这个用法只能用于查找文件,不能用于创建文件 [abcx]表示可以是a、b、c、x中的任意一个;[a-z]表示a-z共26个字母中的任意一个,同理有[a-d]、[0-9]、[1-5]、……;
[!] 匹配括号内字符之外的字符中的任意一个 [!0-9]a*表示不以数字开头且第二个字符为a的文件名;
{a,b,c,x}

{a..d}
匹配括号内的任意一个字符或字符串,以半角逗号,分隔时代表单独的字符本身,逗号分隔的如是多个字符组成的字符串,则匹配到字符串;而以两个点..分隔时代表字符范围。这个用法能用于查找文件,也能用于创建文件 {a..z}{1..9}* 以a到z任意字符开头、第二字符是0-9中任意一个数字的文件
ls -ld /usr/lib*
##  dr-xr-xr-x.  47 root root  4096 7月  13 10:07 /usr/lib
##  dr-xr-xr-x. 144 root root 90112 8月  24 00:10 /usr/lib64
##  drwxr-xr-x.  53 root root 12288 2月  12 2023 /usr/libexec
 
ls -ld /usr/l?*
##  dr-xr-xr-x.  47 root root  4096 7月  13 10:07 /usr/lib
##  dr-xr-xr-x. 144 root root 90112 8月  24 00:10 /usr/lib64
##  drwxr-xr-x.  53 root root 12288 2月  12 2023 /usr/libexec
##  drwxr-xr-x.  14 root root   153 6月  22 2021 /usr/local
 
ls -ld /usr/l*[0-9]*
##  dr-xr-xr-x. 144 root root 90112 8月  24 00:10 /usr/lib64
 
# 如下代码到一个空的文件夹下执行,以便看效果:
touch file_[a-d].txt
ls -l
##  总用量 0
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 'file_[a-d].txt'
 
touch file_{a..d}.txt
ls -l
##  总用量 0
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 'file_[a-d].txt'
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_a.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_b.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_c.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_d.txt
 
ls -l file_[a-c]*
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 file_a.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 file_b.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 file_c.txt
 
ls -l file_{a,c}*
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 file_a.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 file_c.txt
##  2023-08-24 14:07:24 whong@whlab00:/home/whong/test
 
ls -l file*
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 'file_[a-d].txt'
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_a.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_b.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_c.txt
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05  file_d.txt
 
ls -l file_[!a-z]*
##  -rw-rw-r-- 1 whong whong 0 8月  24 14:05 'file_[a-d].txt'
 
mkdir {a,bc,xyz}.txt
ls -ld */
##  drwxrwxr-x 2 whong whong 6 8月  24 14:14 a.txt/
##  drwxrwxr-x 2 whong whong 6 8月  24 14:14 bc.txt/
##  drwxrwxr-x 2 whong whong 6 8月  24 14:14 xyz.txt/
 
ls -ld {bc,a.txt}*
##  drwxrwxr-x 2 whong whong 6 8月  24 14:14 a.txt
##  drwxrwxr-x 2 whong whong 6 8月  24 14:14 bc.txt
 
ls -ld "{bc,a.txt}*"
##  ls: 无法访问'{bc,a.txt}*': 没有那个文件或目录

正则表达式

正则表达式中的一些元字符在通配符中有特殊含义,所以正则表达式需要括号括起来,以免混淆。

元字符 含义 说明
基础正则表达式 . 除换行符以外的任意一个字符
* 前一个字符匹配 ≥ 0 次
^ 行首
$ 行尾
[] 括号内字符中的任意一个
[^] 括号内字符以外的字符中的任意一个
\ 转义,用于取消元字符的特殊含义,使用其本身的字面含义 “\.\.$”匹配以.*两个字符结尾的行
\{n\} 前边的字符被匹配n次 基础正则表达式中需要加上转义符
\{n,\} 前边的字符被匹配至少n次
\{n,m\} 前边的字符被匹配至少n次,至多m次
扩展正则表达式 {n} 前边的字符被匹配n次 拓展的正则表达式中不需要加转义符
支持拓展正则表达式的命令有egrep、awk
grep加上-E选项
{n,} 前边的字符被匹配至少n次
{n,m} 前边的字符被匹配至少n次,至多m次
+ 前边的字符被匹配 ≥ 1 次
? 前边的字符被匹配 ≥ 0 次
| 或者
()

如果以上命令如无法解决问题则告诉我


本网页已被访问9584数;最后编辑时间: 2023/10/06 10:50