你如何爬上 bash 脚本的父目录结构?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3585169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you climb up the parent directory structure of a bash script?
提问by froogz3301
Is there a neater way of climbing up multiple directory levels from the location of a script.
是否有一种更简洁的方法可以从脚本的位置爬上多个目录级别。
This is what I currently have.
这就是我目前所拥有的。
# 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
I would like a neat way of finding the nth level. Any ideas other than putting in a for loop?
我想要一种巧妙的方法来找到第 n 级。除了放入 for 循环之外还有其他想法吗?
回答by Paused until further notice.
dir="/path/to/somewhere/interesting"
saveIFS=$IFS
IFS='/'
parts=($dir)
IFS=$saveIFS
level=${parts[3]}
echo "$level" # output: somewhere
回答by nix
#!/bin/sh
ancestor() {
local n=${1:-1}
(for ((; n != 0; n--)); do cd $(dirname ${PWD}); done; pwd)
}
Usage:
用法:
$ pwd
/home/nix/a/b/c/d/e/f/g
$ ancestor 3
/home/nix/a/b/c/d
回答by DVK
If you're OK with including a Perl command:
如果您同意包含 Perl 命令:
$ pwd
/u1/myuser/dir3/dir4/dir5/dir6/dir7
The first command lists the directory containing first N (in my case 5) directories
第一个命令列出包含前 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
The second command lists the directory N levels up (in my case 5) directories (I think you wanted the latter).
第二个命令列出了 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
To use it in your bash script, of course:
当然,要在 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";')
回答by Dummy00001
Any ideas other than putting in a for loop?
除了放入 for 循环之外还有其他想法吗?
In shells, you can't avoid the loop, because traditionally they do not support regexp, but glob matching instead. And glob patterns do not support the any sort of repeat counters.
在 shell 中,您无法避免循环,因为传统上它们不支持正则表达式,而是支持 glob 匹配。并且 glob 模式不支持任何类型的重复计数器。
And BTW, simplest way is to do it in shell is: echo $(cd $PWD/../.. && echo $PWD)where the /../..makes it strip two levels.
和BTW,最简单的方法是做壳是:echo $(cd $PWD/../.. && echo $PWD)在/../..使得地带的两个级别。
With tiny bit of Perl that would be:
使用一点点 Perl 将是:
perl -e '$ENV{PWD} =~ m@^(.*)(/[^/]+){2}$@ && print ,"\n"'
The {2}in the Perl's regular expression is the number of directory entries to strip. Or making it configurable:
的{2}在Perl的正则表达式是剥离目录条目的数量。或使其可配置:
N=2
perl -e '$ENV{PWD} =~ m@^(.*)(/[^/]+){'$N'}$@ && print ,"\n"'
One can also use Perl's split(), join()and splice()for the purpose, e.g.:
也可以使用 Perl 的split()、join()和splice()来达到目的,例如:
perl -e '@a=split("/", $ENV{PWD}); print join("/", splice(@a, 0, -2)),"\n"'
where -2says that from the path the last two entries has to be removed.
where-2说必须从路径中删除最后两个条目。
回答by icetan
A solution without loops would be to use recursion. I wanted to find a config file for a script by traversing backwards up from my current working directory.
没有循环的解决方案是使用递归。我想通过从我当前的工作目录向后遍历来查找脚本的配置文件。
rtrav() { test -e $2/$1 && echo $2 || { test $2 != / && rtrav $1 `dirname $2`;}; }
rtrav() { test -e $2/$1 && echo $2 || { test $2 != / && rtrav $1 `dirname $2`;}; }
To check if the current directory is in a GIT repo: rtrav .git $PWD
要检查当前目录是否在 GIT 存储库中: rtrav .git $PWD
rtravwill check the existence of a filename given by the first argument in each parent folder of the one given as the second argument. Printing the directory path where the file was found or exiting with an error code if the file was not found.
rtrav将检查作为第二个参数给出的每个父文件夹中第一个参数给出的文件名是否存在。打印找到文件的目录路径,如果未找到文件,则以错误代码退出。
The predicate (test -e $2/$1) could be swapped for checking of a counter that indicates the traversal depth.
test -e $2/$1可以交换谓词 ( ) 以检查指示遍历深度的计数器。
回答by Christian Bongiorno
This allows you to work your way up until whatever condition is desired
这使您可以按照自己的方式工作,直到需要任何条件
WORKDIR=$PWD
until test -d "$WORKDIR/infra/codedeploy"; do
# get the full path of the script
WORKDIR=$(dirname $WORKDIR)
done
回答by l0b0
Two levels above the script directory:
脚本目录之上两级:
echo "$(readlink -f -- "$(dirname -- " #resolve the run dir where this scripts is placed
##代码## =~ m/^(.*)(\|\/)(.*)\.([a-z]*)/;
$RunDir = ;
#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 ;
")/../..")"
All the quoting and --are to avoid problems with tricky paths.
所有的引用--都是为了避免棘手路径的问题。
回答by Yordan Georgiev
This method uses the actual full path to the perl script itself ... TIMTOWTDI You could just easily replace the $RunDir with the path you would like to start with ...
此方法使用 perl 脚本本身的实际完整路径... TIMTOWTDI 您可以轻松地将 $RunDir 替换为您想要开始的路径...
##代码##
