你如何爬上bash脚本的父目录结构?

时间:2010-08-27 14:31:45

标签: perl bash directory

是否有更简洁的方法从脚本位置爬上多个目录级别。

这就是我现在所拥有的。

# get the full path of the script
D=$(cd ${0%/*} && echo $PWD/${0##*/})

D=$(dirname $D)
D=$(dirname $D)
D=$(dirname $D)

# second level parent directory of script
echo $D

我想要一个找到第n级的简洁方法。除了进行for循环之外的任何想法?

8 个答案:

答案 0 :(得分:5)

dir="/path/to/somewhere/interesting"
saveIFS=$IFS
IFS='/'
parts=($dir)
IFS=$saveIFS
level=${parts[3]}
echo "$level"    # output: somewhere

答案 1 :(得分:2)

#!/bin/sh
ancestor() {
  local n=${1:-1}
  (for ((; n != 0; n--)); do cd $(dirname ${PWD}); done; pwd)
}

用法:

 $ pwd
 /home/nix/a/b/c/d/e/f/g

 $ ancestor 3
 /home/nix/a/b/c/d

答案 2 :(得分:1)

如果您可以使用Perl命令:

$ pwd
/u1/myuser/dir3/dir4/dir5/dir6/dir7

第一个命令列出包含前N个(在我的例子中为5个)目录

的目录
$ perl-e 'use File::Spec; \
          my @dirs = File::Spec->splitdir( \
             File::Spec->rel2abs( File::Spec->curdir() ) ); \
          my @dirs2=@dirs[0..5]; print File::Spec->catdir(@dirs2) . "\n";'
/u1/myuser/dir3/dir4/dir5

第二个命令列出目录N级别(在我的情况下是5个)目录(我想你想要后者)。

$ perl -e 'use File::Spec; \
           my @dirs = File::Spec->splitdir( \
              File::Spec->rel2abs( File::Spec->curdir() ) ); \
           my @dirs2=@dirs[0..$#dir-5]; print File::Spec->catdir(@dirs2)."\n";'
/u1/myuser

要在bash脚本中使用它,当然:

D=$(perl -e 'use File::Spec; \
           my @dirs = File::Spec->splitdir( \
              File::Spec->rel2abs( File::Spec->curdir() ) ); \
           my @dirs2=@dirs[0..$#dir-5]; print File::Spec->catdir(@dirs2)."\n";')

答案 3 :(得分:1)

  

除了进行for循环之外的任何想法?

在shell中,你无法避免循环,因为传统上它们不支持regexp,而是支持glob匹配。并且glob模式不支持任何类型的重复计数器。

BTW,最简单的方法是在shell中执行:echo $(cd $PWD/../.. && echo $PWD) /../..使其剥离两个级别。

Perl的一点点就是:

perl -e '$ENV{PWD} =~ m@^(.*)(/[^/]+){2}$@ && print $1,"\n"'

Perl正则表达式中的{2}是要剥离的目录条目数。或者使其可配置:

N=2
perl -e '$ENV{PWD} =~ m@^(.*)(/[^/]+){'$N'}$@ && print $1,"\n"'

也可以使用Perl的split()join()splice()来达到目的,例如:

perl -e '@a=split("/", $ENV{PWD}); print join("/", splice(@a, 0, -2)),"\n"'

其中-2表示必须从路径中移除最后两个条目。

答案 4 :(得分:1)

没有循环的解决方案是使用递归。我想通过从当前工作目录向后遍历来查找脚本的配置文件。

rtrav() { test -e $2/$1 && echo $2 || { test $2 != / && rtrav $1 `dirname $2`;}; }

检查当前目录是否在GIT仓库中:rtrav .git $PWD

rtrav将检查第二个参数给定的每个父文件夹中第一个参数给出的文件名是否存在。打印找到文件的目录路径,如果找不到该文件,则输入错误代码。

可以交换谓词(test -e $2/$1)来检查指示遍历深度的计数器。

答案 5 :(得分:0)

脚本目录上方两级:

echo "$(readlink -f -- "$(dirname -- "$0")/../..")"

所有引用和--都是为了避免棘手路径出现问题。

答案 6 :(得分:0)

此方法使用perl脚本本身的实际完整路径... TIMTOWTDI 您可以轻松地将$ RunDir替换为您想要开始的路径...

        #resolve the run dir where this scripts is placed
        $0 =~ m/^(.*)(\\|\/)(.*)\.([a-z]*)/; 
        $RunDir = $1 ; 
        #change the \'s to /'s if we are on Windows
        $RunDir =~s/\\/\//gi ; 
        my @DirParts = split ('/' , $RunDir) ; 
        for (my $count=0; $count < 4; $count++) {   pop @DirParts ;     }

        $confHolder->{'ProductBaseDir'} = $ProductBaseDir ; 

答案 7 :(得分:0)

这使您可以逐步提高工作水平,直到需要任何条件

WORKDIR=$PWD
until test -d "$WORKDIR/infra/codedeploy"; do
  # get the full path of the script

  WORKDIR=$(dirname $WORKDIR)
done