当前位置: 首页 > Linux

Bash技巧:简单快速 cd 到多层上级目录的 Shell 脚本

时间:2023-04-06 18:21:02 Linux

bash技巧:cd到多层上层目录./".的简单快速shell脚本输入快的时候中间经常多一个点'.'或者少一个点'.',这需要删除重新进入,在实际的开发工作中,尤其是Android系统的开发中,源代码目录可能会有多级子目录,当进入一个目录结构很深的子目录时,如果想返回到一个具体的多级父目录,需要手动输入多个“../”,非常麻烦,而且容易输入错误。为了简化输入,减少输入错误,本文介绍一个名为cdup.sh的shell脚本。脚本接收一个整型参数,指定返回多少层上级目录,可以非常方便的返回多层上级目录,提高工作效率,例如执行sourcecdup.sh5命令为相当于执行cd../../../../../命令。给出的数字5指定返回到第5级父目录。后面会介绍如何设置命令别名,避免输入像sourcecdup.sh这样的字符,可以简化为像up这样输入5由于shell脚本默认运行在子shell中,cd命令只能改变工作目录当前的外壳。所以在shell脚本中执行cd命令不能改变父shell的工作目录。为了在脚本执行后保留cd后的目录,需要使用source命令来执行shell脚本。使用source命令执行shell脚本将在当前shell下运行,而不是在子shell中运行。脚本代码列表cdup.sh脚本的具体代码如下。代码中大部分关键代码都做了详细的注释,方便阅读。本文后面也会对一些关键点进行说明,以帮助理解。#!/bin/bash#当要cd到多层父目录时,需要输入cd../../../等等多个“../”。#为了简化input,当前脚本可以处理一个Integer参数,指定返回的上一级目录。#例如sourcecdup.sh3相当于cd../../../#为了在脚本执行后保留cd后的目录,需要使用source命令#来执行脚本。可以在~/.bashrc文件中加入如下别名,方便执行:#aliasup='sourcecdup.sh'#后续执行up3命令相当于cd../../../#这里假定cdup.sh脚本位于PATH指定的寻址目录中。例如,/usr/bin目录。#如果cdup.sh脚本没有放在默认寻址目录下,请指定完整的绝对路径cdup.sh3相当于cd../../../NOTE,可以使用aliasup='sourcecdup.sh'设置up别名,方便执行。"}if[$#-ne1];thencdup_show_help#当前脚本应该被source命令调用,不能执行exit命令,#否则调用脚本的shell会退出。下面是return命令返回的。return1fiUPDIR_PATH="../"#根据传入的number参数,计算返回上层目录的第几层,并将结果写入标准输出count_updirs(){#第一个给定的A参数指定如何返回多级父目录返回本地count=$1localupdirs=""while((--count>=0));do#当不使用算术扩展时,bash的+=运算符默认会连接字符串。#下面的语句将多个“../”进行拼接得到类似“../../../”的效果。updirs+=${UPDIR_PATH}doneecho${updirs}}target_dir="$(count_updirs$1)"#使用\cd指定不使用alias别名,执行原cd命令\cd"${target_dir}"返回码关键点说明建议设置命令Alias执行当前脚本上面说了需要使用source命令来执行cdup.sh脚本,这样脚本执行后可以一直保存在cd后的目录中。即执行时需要写成sourcecdup.sh。这需要输入更多的字符,而且很容易忘记提供source命令。为了方便输入,在脚本注释中,建议设置命令别名来执行当前脚本。例如在~/.bashrc文件中添加如下语句设置命令别名:aliasup='sourcecdup.sh'添加该语句后,在当前终端中,需要执行source~/.bashrc命令,别名生效。也可以重新打开终端,别名在新打开的终端默认生效。别名生效后,可以使用up命令执行cdup.sh脚本。例如,up3命令等同于sourcecdup.sh3命令。这里假设cdup.sh脚本放在PATH全局变量指定的寻址目录下,可以通过文件名执行,不需要指定文件的路径。如果脚本没有放在默认寻址目录下,则需要提供文件的绝对路径。在cd命令前加上反斜杠,表示不使用别名bash中支持设置命令别名。如果将命令别名设置为cd字符串,则执行cd命令将执行别名指定的命令。即原本切换工作目录的cd命令不会执行。为避免此问题,请使用\cd指定将执行cd命令本身而不是使用别名。在cdup.sh脚本中使用\cd表示法以确保可以切换工作目录。查看manbash对alias别名的描述,并没有明确提到不能通过在命令前加反斜杠来使用别名。这是基于反斜杠转义字符的作用和别名的处理逻辑的特殊用法。对于\cd的写法,可以不用命令别名的相关说明,详细如下。查看manbash对反斜杠\的描述,如下所示:不带引号的反斜杠(\)是转义字符。它保留下一个字符的字面值,除外。也就是说,当反斜杠\行没有包含在任何引号中时,它可以将其后面的下一个字符保留为本身。而且,经过bash处理后,\字符将被删除,只留下下一个字符本身。例如,在bash中,\c获取不带任何引号的字符c。具体例子如下:$echo\cc$echo\cdcd可以看到echo\c命令打印的是字符c,而不是“c”字符串。echo\cd命令打印字符串“cd”。实际上,\c得到字符c后,将字符c与字符d组合,组成“cd”字符串。检查manbash对alias别名的描述,如下所示:检查每个简单命令的第一个单词(如果未加引号)以查看它是否具有别名。如果是这样,该词将替换为别名的文本。也就是说,bash会根据命令的第一个未加引号的字符检查别名。如果是这样,请将此命令别名替换为指定的命令。在bash中,无法将命令别名的第一个字符设置为反斜杠。具体例子如下:$alias\testcd='cd../../'$alias|grepcdaliastestcd='cd../../'这里先执行alias\testcd='cd../../'命令设置别名。从输入的参数来看,似乎设置的别名是\testcd。但是使用alias命令打印出所有的命令别名,使用grep过滤掉包含cd的行。可以看到,实际设置的别名是testcd。此别名的第一个字符不是反斜杠。如前所述,bash去除了未包含在引号中的反斜杠。查看GNUbash的在线帮助链接https://www.gnu.org/software/...,有如下说明:3.1.1ShellOperation2。将输入分解为单词和运算符,遵守引用中描述的引用规则。这些令牌由元字符分隔。别名扩展由这一步执行。4.执行各种shell扩展,将扩展的标记分解为文件名和命令和参数的列表。3.5.9引用删除在前面的扩展之后,所有未引用的'',''',和'"'不是由上述扩展之一产生的被删除。也就是说,bash将在QuoteRemoval阶段删除反斜杠\字符。引号删除在shell扩展之后执行。别名在shell扩展之前判断所以,bash在判断别名的时候,也会看到反斜杠\字符。也就是说,执行\cd命令时,会看到第一个字符是\。前面解释过,第一个字符是commandalias不能设置为反斜杠,则找不到\cd对应的别名,不会进行别名替换。QuoteRemoval阶段后,反斜杠去掉一行,只剩下cd命令。此时此时,判断别名的阶段已经过去,所以执行cd命令本身,不会执行名为cd的命令别名。也就是严格来说,在命令前加一个反斜杠,并不是不使用别名。相反,无法找到以反斜杠开头的别名,因此不会扩展别名。通俗地说,可以简单理解为在命令前加一个反斜杠,表示不使用别名。执行当前脚本示例使用上述up命令的别名执行sourcecdup.sh命令。具体执行结果如下:[frameworks/base/services/core/java/com/android/server]$cd../../../../../[frameworks/base/services]$cd-frameworks/base/services/core/java/com/android/server[frameworks/base/services/core/java/com/android/server]$up5[frameworks/base/services]$在这个例子中,方括号中间显示的目录路径为当前shell的工作目录。可以看到,cd../../../../../命令返回到5级父目录。然后执行cd-命令回到原来的子目录。再次执行up5命令,返回到第五层的上层目录。up5命令的效果和cd../../../../../命令一样,但是输入很简单,容易出错。