bash 命令提示符
作为许多Linux和Unix变体的默认外壳,Bash包括各种未被充分利用的功能,因此很难决定讨论什么。 最终,我决定专注于使日常活动变得更轻松的Bash技巧。
作为顾问,我看到了多种多样的环境和工作风格。 我利用这种经验将技巧分为四大类:终端和线路技巧,导航和文件,历史记录以及有用的命令。 这些类别完全是任意的,比起任何确定的分类,它们更能组织我自己的思想。 这里包含的许多技巧可能在主观上适合多个类别。
事不宜迟,这里是我遇到的一些最有用的Bash技巧。
使用Bash历史记录
提高生产力的最好方法之一就是学习更有效地使用Bash历史记录。 考虑到这一点,在多用户环境中可能要做的最重要的调整之一就是对您的Shell启用histappend
选项。 为此,只需运行以下命令:
shopt -s histappend
这允许多个终端会话同时写入历史记录。 在大多数环境中, 未启用此选项。 这意味着,如果您打开了多个Bash会话(本地或通过SSH),历史记录通常会丢失。
另一个常见的任务是使用sudo
重复最后一个命令。 例如,假设您要创建目录mkdir /etc/ansible/facts.d
。 除非您是root用户,否则此命令将失败。 根据我的观察,大多数用户单击up
箭头,滚动到该行的开头,然后添加sudo
命令。 有一种更简单的方法。 只需运行以下命令:
sudo !!
Bash将先运行sudo
,然后再运行上一个命令的全部。 依序运行时的样子如下:
[ user
@ centos ~
] $
mkdir
-p
/ etc
/ ansible
/ facts.d
mkdir: cannot create directory ‘
/ etc
/ ansible’: Permission denied
[ user
@ centos ~
] $
sudo
!!
sudo
mkdir
-p
/ etc
/ ansible
/ facts.d
当!!
运行后,完整的命令将回显到终端,因此您知道刚刚执行的操作。
相似但使用的很少!*
快捷方式。 这告诉Bash您希望在当前命令中重复前一个命令的所有* arguments * 。 这对于具有许多要重用的参数的命令可能很有用。 一个简单的示例是创建一堆文件,然后更改它们的权限:
[ user
@ centos tmp
] $
touch file1 file2 file3 file4
[ user
@ centos tmp
] $
chmod
777
!*
chmod
777 file1 file2 file3 file4
仅在特定情况下方便使用,但可以节省一些击键。
说到保存击键,让我们谈谈在历史记录中查找命令。 大多数用户将执行以下操作:
history | grep < some command >
但是,有一种更简便的方法来搜索历史记录。 如果按
ctrl + r
Bash将对您的历史记录进行反向搜索。 当您开始键入内容时,结果将开始出现。 例如:
( reverse-i-search ) ` hist ': shopt -s histappend
在上面的示例中,我键入了hist
,它与我们前面介绍的shopt
命令匹配。 如果继续按ctrl + r
,Bash将继续向后搜索所有其他匹配项。
我们的最后一个技巧并不是一个有用的命令,而是可以用来计数和显示历史上最常用的命令的一个技巧。
[ user
@ centos tmp
] $
history
|
awk
'BEGIN {FS="[ \t]+|\\|"} {print $3}'
|
sort
|
uniq
-c
|
sort
-nr
|
head
81
ssh
50
sudo
46
ls
45
ping
39
cd
29 nvidia-xrun
20
nmap
19
export
在此示例中,您可以看到ssh
是迄今为止我历史上最常用的命令。
导航和文件命名
tab
键一次即可为您完成措辞。
如果只有一个完全匹配,则此方法有效。
但是,您可能不知道,如果您两次单击tab
,它将根据您输入的内容显示所有匹配项。
例如:
[ user
@ centos tmp
] $
cd
/ lib
< tab
>< tab
>
lib
/ lib64
/
这对于文件系统导航非常有用。 另一个有用的技巧是在外壳中启用cdspell
。 您可以通过发出shopt -s cdspell
命令来执行此操作。 这将有助于纠正您的错别字:
[ user
@ centos etc
] $
cd
/ tpm
/ tmp
[ user
@ centos tmp
] $
cd
/ ect
/ etc
这不是完美的,但一点点帮助!
成功更改目录后,如果需要返回到先前的目录怎么办? 如果您对目录树的了解不是很深,那么这没什么大不了的。 但是,如果您走的路很深,例如/var/lib/flatpak/exports/share/applications/
,则可以输入:
cd / va < tab >/ lib / fla < tab >/ ex < tab >/ sh < tab >/ app < tab >
幸运的是,Bash会记住您以前的目录,您只需键入cd -
即可返回该目录。 看起来像这样:
[ user
@ centos applications
] $
pwd
/ var
/ lib
/ flatpak
/ exports
/ share
/ applications
[ user
@ centos applications
] $
cd
/ tmp
[ user
@ centos tmp
] $
pwd
/ tmp
[ user
@ centos tmp
] $
cd -
/ var
/ lib
/ flatpak
/ exports
/ share
/ applications
一切都很好,但是如果您有一堆想要轻松导航的目录怎么办? Bash也覆盖了那里。 您可以设置一个变量,以帮助您更有效地导航。 这是一个例子:
[ user
@ centos applications
] $
export
CDPATH =
'~:/var/log:/etc'
[ user
@ centos applications
] $
cd hp
/ etc
/ hp
[ user
@ centos hp
] $
cd Downloads
/ home
/ user
/ Downloads
[ user
@ centos Downloads
] $
cd ansible
/ etc
/ ansible
[ user
@ centos Downloads
] $
cd journal
/ var
/ log
/ journal
在上面的示例中,我设置了我的主目录(以代字号~
), /var/log
和/etc
当您引用它们时,这些目录顶层的所有内容都会自动填写。 找不到不在CDPATH
列出的目录的目录。 例如,如果您要访问的目录是/etc/ansible/facts.d/
,则无法通过输入cd facts.d
来完成此cd facts.d
。 这是因为,虽然该目录ansible
下发现/etc
, facts.d
不是。 因此, CDPATH
对于到达您经常访问的树的顶部很有用,但是当您浏览大型文件夹结构时,管理起来可能很麻烦。
最后,让我们谈谈每个人在某个时候都做的两个常见用例:更改文件扩展名和重命名文件。 乍一看,这听起来似乎是一样的事情,但是Bash提供了一些不同的技巧来完成这些任务。
尽管这可能是“卑鄙的”操作,但大多数用户在某个时候都需要为其正在处理的文件创建快速副本。 大多数将完全复制文件名,并简单地附加文件扩展名,如.old
或.bak
。 Bash中有一个快速的快捷方式。 假设您有一个想要保留其副本的文件名,例如spideroak_inotify_db.07pkh3
。 您可以输入:
cp spideroak_inotify_db.07pkh3 spideroak_inotify_db.07pkh3.bak
您可以通过使用复制/粘贴操作,使用完整的选项卡,可能使用快捷方式之一来重复自变量或简单地输入整个内容来快速完成此工作。 但是,一旦习惯了键入以下命令,它应该会变得更快:
cp spideroak_inotify_db.07pkh3 { ,.old }
这(您可以猜测)通过将.old
文件扩展名附加到文件来复制文件。 您可能会说这很好,但是我想一次重命名大量文件。 当然,您可以编写一个for循环来处理这些问题(实际上,我经常为复杂的事情做这件事),但是为什么当有一个方便的实用程序称为rename
时,您为什么要这么做? 在Debian / Ubuntu和CentOS / Arch之间,此实用程序的用法有所不同。 基于Debian的重命名使用类似于SED的语法:
user
@ ubuntu-
1604 :
/ tmp$
for x
in
`
seq
1
5
` ;
do
touch old_text_file_
${x} .txt;
done
user
@ ubuntu-
1604 :
/ tmp$
ls old_text_file_
*
old_text_file_1.txt old_text_file_3.txt old_text_file_5.txt
old_text_file_2.txt old_text_file_4.txt
user
@ ubuntu-
1604 :
/ tmp$ rename
's/old_text_file/shiney_new_doc/'
* .txt
user
@ ubuntu-
1604 :
/ tmp$
ls shiney_new_doc_
*
shiney_new_doc_1.txt shiney_new_doc_3.txt shiney_new_doc_5.txt
shiney_new_doc_2.txt shiney_new_doc_4.txt
在CentOS或Arch框上,外观类似:
[ user
@ centos
/ tmp
] $
for x
in
`
seq
1
5
` ;
do
touch old_text_file_
${x} .txt;
done
[ user
@ centos
/ tmp
] $
ls old_text_file_
*
old_text_file_1.txt old_text_file_3.txt old_text_file_5.txt
old_text_file_2.txt old_text_file_4.txt
[ user
@ centos tmp
] $ rename old_text_file centos_new_doc
* .txt
[ user
@ centos tmp
] $
ls centos_new_doc_
*
centos_new_doc_1.txt centos_new_doc_3.txt centos_new_doc_5.txt
centos_new_doc_2.txt centos_new_doc_4.txt
Bash键绑定
Bash有很多内置的键盘快捷键。 您可以通过键入bind -p
找到它们的列表。 我认为突出显示一些内容将很有用,尽管其中一些可能是众所周知的。
ctrl + _
( undo
)
ctrl + t
( swap two characters
)
ALT + t
( swap two words
)
ALT + .
( prints
last argument from previous
command
)
ctrl + x +
*
( expand glob
/ star
)
ctrl + arrow
( move forward a word
)
ALT + f
( move forward a word
)
ALT + b
( move backward a word
)
ctrl + x + ctrl + e
( opens the
command string
in an editor so that you can edit it before execution
)
ctrl + e
( move cursor to end
)
ctrl + a
( move cursor to start
)
ctrl + xx
( move to the opposite end of the line
)
ctrl + u
( cuts everything before the cursor
)
ctrl + k
( cuts everything after the cursor
)
ctrl + y
( pastes from the buffer
)
ctrl + l
( clears
screen
) s
我不会讨论更明显的内容。 但是,我发现的一些最有用的快捷方式是使您删除单词(或文本的一部分)并撤消它们的快捷方式。 假设您要使用systemd
停止一堆服务,但是您只想在某些操作完成后启动其中一些服务。 您可能会执行以下操作:
systemctl stop httpd mariadb nfs smbd
< hit the up button to get the previous
command
>
< use
'ctrl + w' to remove the unwanted arguments
>
但是,如果您删除了太多,该怎么办? 没问题-只需使用ctrl + _
撤消上一次编辑。
其他剪切命令使您可以快速删除从光标到行尾或行首的所有内容(分别使用Ctrl + k
和Ctrl + u
)。 这具有将剪切后的文本放置到终端缓冲区中的附加好处,因此您以后可以将其粘贴(使用ctrl + y
)。 这些命令在这里很难演示,因此我强烈建议您自己尝试一下。
最后但并非最不重要的一点是,我想提到一种很少使用的组合键,在密闭环境(例如容器)中非常方便。 如果您的命令在前面的输出中显示为乱码,那么有一个解决方案:按ctrl + x + ctrl + e
可以在环境变量EDITOR中设置的任何编辑器中打开命令。 这将允许您在文本编辑器中(可能)可以换行的文本编辑长命令或乱码。 保存工作并退出,就像处理普通文件一样,将在离开编辑器后执行命令。
杂项提示
您可能会发现在Bash shell中显示颜色可以增强您的体验。 如果您使用的会话未启用着色,则可以在.bash_profile
放置以下命令,以为会话添加颜色。 这些非常简单,不需要深入说明:
# enable colors
eval
" `dircolors -b` "
# force ls to always use color and type indicators
alias
ls =
'ls -hF --color=auto'
# make the dir command work kinda like in windows (long format)
alias
dir =
'ls --color=auto --format=long'
# make grep highlight results using color
export
GREP_OPTIONS =
'--color=auto'
# Add some colour to LESS/MAN pages
export
LESS_TERMCAP_mb =$
'\E[01;31m'
export
LESS_TERMCAP_md =$
'\E[01;33m'
export
LESS_TERMCAP_me =$
'\E[0m'
export
LESS_TERMCAP_se =$
'\E[0m'
export
LESS_TERMCAP_so =$
'\E[01;42;30m'
export
LESS_TERMCAP_ue =$
'\E[0m'
export
LESS_TERMCAP_us =$
'\E[01;36m'
除了调整Bash中的各种选项外,您还可以使用一些巧妙的技巧来节省时间。 例如,要背对背运行两个命令,而不管每个命令的退出状态如何,请使用;
分隔命令,如下所示:
[ user @ centos / tmp ] $ du -hsc * ; df -h
这只是计算当前目录中每个文件占用(并求和)的空间量,然后向系统查询每个块设备的磁盘使用情况。 无论du
命令生成任何错误,这些命令都将运行。
如果您希望在成功完成第一个命令后采取措施怎么办? 您可以使用&&
简写表示仅在第一个命令返回成功退出状态时才要运行第二个命令。 例如,假设您仅在更新成功的情况下才希望重新引导计算机:
[ root @ arch ~ ] $ pacman -Syu --noconfirm && reboot
有时在运行命令时,您可能希望捕获其输出。 大多数人都知道tee
命令,该命令会将标准输出复制到终端和文件中。 但是,如果要从strace
捕获更复杂的输出,则需要开始使用I / O重定向 。 I / O重定向的详细信息超出了本文的范围,但是出于我们的目的,我们关注STDOUT
和STDERR
。 准确捕获所见内容的最佳方法是将两个文件合并到一个文件中。 为此,请使用2>&1
重定向。
[ root @ arch ~ ] $ strace -p 1140 > strace_output.txt 2 >& 1
这会将所有相关输出放入名为strace_output.txt
的文件中,以供以后查看。
有时,在长时间运行的命令中,您可能需要暂停执行任务。 您可以使用“停止”快捷键ctrl + z
停止(但不能终止)工作。 作业被添加到作业队列中,但是直到您将其恢复之前,您将不再看到该作业。 可以通过使用前台命令fg
在以后的时间恢复该作业。
另外,您也可以使用ctrl + s
暂停作业。 作业及其输出保留在终端前台,并且不将外壳程序的使用返回给用户。 可以通过按ctrl + q
恢复作业。
如果您在许多终端处于打开状态的图形环境中工作,则可能会很方便使用用于复制和粘贴输出的键盘快捷键。 为此,请使用以下快捷方式:
# Copies highlighted text
ctrl +
shift + c
# Pastes text in buffer
ctrl +
shift + v
假设在一个正在执行的命令的输出中,您看到另一个正在执行的命令,并且您想获得更多信息。 有几种方法可以做到这一点。 如果此命令在您的路径中某处,则可以运行which
命令以找出该命令在磁盘上的位置:
[ root
@
arch ~
] $
which
ls
/ usr
/ bin
/
ls
有了这些信息,您可以使用file
命令检查二进制file
:
[ root
@
arch ~
] $
file
/ usr
/ bin
/
ls
/ usr
/ bin
/ ls: ELF
64 -bit LSB pie executable x86-
64 , version
1
( SYSV
) , dynamically linked, interpreter
/ lib64
/ ld-linux-x86-
64 .so.2,
for GNU
/ Linux 3.2.0, BuildID
[ sha1
] =d4e02b88e596e4f82c6cc62a5bc4ce5827209a49, stripped
您可以看到各种信息,但是对于大多数用户而言,最重要的是ELF 64-bit LSB
废话。 实质上,这意味着它是预编译的二进制文件,而不是脚本或其他类型的可执行文件。 您可以用来检查命令的相关工具是command
工具本身。 只需运行command -V <command>
将为您提供不同类型的信息:
[ root
@
arch ~
] $
command
-V
ls
ls is aliased to
`
ls
--color =auto
`
[ root
@
arch ~
] $
command
-V
bash
bash is
/ usr
/ bin
/
bash
[ root
@
arch ~
] $
command
-V
shopt
shopt is a shell
builtin
最后但并非最不重要的一点是,我最喜欢的技巧之一是echo
命令,尤其是在使用容器或在我几乎不了解或无法控制的环境中使用时。 该命令可用于执行所有操作,从检查以确保您的for
循环将按预期的顺序运行,到允许您检查远程端口是否打开。 检查开放端口的语法非常简单: echo > /dev/<udp or tcp>/<server ip>/<port>
。 例如:
user@ubuntu-1604:~$
echo
>
/ dev
/ tcp
/ 192.168.99.99
/
222
-bash: connect: Connection refused
-bash:
/ dev
/ tcp
/ 192.168.99.99
/
222 : Connection refused
user@ubuntu-1604:~$
echo
>
/ dev
/ tcp
/ 192.168.99.99
/
22
如果端口与您尝试建立的连接类型无关,则会收到“ Connection refused
消息。 如果成功发送了数据包,将不会有输出。
我希望这些技巧能使Bash更加高效和有趣。 Bash中隐藏的技巧比我在这里列出的要多。 您最喜欢什么?
附录1.涵盖的提示和技巧列表
# History related
ctrl + r
( reverse search
)
!!
( rerun
last
command
)
!*
( reuse arguments from previous
command
)
! $
( use
last argument of
last
command
)
shopt
-s histappend
( allow multiple terminals to
write to the
history
file
)
history
|
awk
'BEGIN {FS="[ \t]+|\\|"} {print $3}'
|
sort
|
uniq
-c
|
sort
-nr
|
head
( list the most used
history commands
)
# File and navigation
cp
/ home
/ foo
/ realllylongname.cpp
{ ,-old
}
cd -
rename
's/text_to_find/been_renamed/'
* .txt
export
CDPATH =
'/var/log:~'
( variable is used with the
cd built-in.
)
# Colourize bash
# enable colors
eval
" `dircolors -b` "
# force ls to always use color and type indicators
alias
ls =
'ls -hF --color=auto'
# make the dir command work kinda like in windows (long format)
alias
dir =
'ls --color=auto --format=long'
# make grep highlight results using color
export
GREP_OPTIONS =
'--color=auto'
export
LESS_TERMCAP_mb =$
'\E[01;31m'
export
LESS_TERMCAP_md =$
'\E[01;33m'
export
LESS_TERMCAP_me =$
'\E[0m'
export
LESS_TERMCAP_se =$
'\E[0m'
# end the info box
export
LESS_TERMCAP_so =$
'\E[01;42;30m'
# begin the info box
export
LESS_TERMCAP_ue =$
'\E[0m'
export
LESS_TERMCAP_us =$
'\E[01;36m'
# Bash shortcuts
shopt
-s cdspell
( corrects typoos
)
ctrl + _
( undo
)
ctrl + arrow
( move forward a word
)
ctrl + a
( move cursor to start
)
ctrl + e
( move cursor to end
)
ctrl + k
( cuts everything after the cursor
)
ctrl + l
( clears
screen
)
ctrl + q
( resume
command that is
in the foreground
)
ctrl + s
( pause a long running
command
in the foreground
)
ctrl + t
( swap two characters
)
ctrl + u
( cuts everything before the cursor
)
ctrl + x + ctrl + e
( opens the
command string
in an editor so that you can edit it before it runs
)
ctrl + x +
*
( expand glob
/ star
)
ctrl + xx
( move to the opposite end of the line
)
ctrl + y
( pastes from the buffer
)
ctrl +
shift + c
/ v
( copy
/ paste into terminal
)
# Running commands in sequence
&&
( run second
command
if the first is successful
)
;
( run second
command regardless of success of first one
)
# Redirecting I/O
2
>&
1
( redirect stdout and stderr to a
file
)
# check for open ports
echo
>
/ dev
/ tcp
/< server
ip
>/< port
>
``
( use back ticks to shell out
)
# Examine executable
which
<
command
>
file
< path
/ to
/
file
>
command
-V
< some
command binary
>
( tells you whether
< some binary
> is a built-in, binary or
alias
)
bash 命令提示符