在 Bash 中获取目录的父目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8426058/
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
Getting the parent of a directory in Bash
提问by YTKColumba
If I have a file path such as...
如果我有一个文件路径,例如...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
How do I change the string so it will be the parent directory?
如何更改字符串使其成为父目录?
e.g.
例如
/home/smith/Desktop
/home/smith/Desktop/
回答by Michael Hoffman
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Works if there is a trailing slash, too.
如果尾随斜线也有效。
回答by Andreas Spindler
回答by Endu A-d
Just use echo $(cd ../ && pwd)
while working in the directory whose parent dir you want to find out. This chain also has the added benefit of not having trailing slashes.
只需echo $(cd ../ && pwd)
在要查找其父目录的目录中工作时使用。这个链还有一个额外的好处,就是没有尾部斜杠。
回答by Riaz Rizvi
Clearly the parent directory is given by simply appending the dot-dot filename:
很明显,父目录是通过简单地附加点-点文件名来给出的:
/home/smith/Desktop/Test/.. # unresolved path
But you must want the resolvedpath (an absolute path without any dot-dot path components):
但是您必须想要解析路径(没有任何点-点路径组件的绝对路径):
/home/smith/Desktop # resolved path
The problem with the top answers that use dirname
, is that they don't work when you enter a path with dot-dots:
使用dirname
,的最佳答案的问题在于,当您输入带有点的路径时,它们不起作用:
$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/.. # not fully resolved
This is more powerful:
这是更强大的:
dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
You can feed it /home/smith/Desktop/Test/..
, but also more complex paths like:
您可以提供它/home/smith/Desktop/Test/..
,但也可以提供更复杂的路径,例如:
$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users # the fully resolved path!
EDIT: If it doesn't work, check that your cd
hasn't been modified, as is sometimes common practice,
编辑:如果它不起作用,请检查您cd
是否没有被修改,这是有时的常见做法,
$ which cd
cd is a function #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
builtin cd "$@";
ls -FGAhp
}
...
回答by Jon Egeland
回答by Stéphane Gourichon
Motivation for another answer
另一个答案的动机
I like very short, clear, guaranteed code. Bonus point if it does not run an external program, since the day you need to process a huge number of entries, it will be noticeably faster.
我喜欢非常简短、清晰、有保证的代码。如果它不运行外部程序,那么奖励点,因为您需要处理大量条目的那一天,它会明显更快。
Principle
原则
Not sure about what guarantees you have and want, so offering anyway.
不确定您拥有和想要的保证,因此无论如何都要提供。
If you have guarantees you can do it with very short code. The idea is to use bash text substitution feature to cut the last slash and whatever follows.
如果你有保证,你可以用很短的代码来做到这一点。这个想法是使用 bash 文本替换功能来剪切最后一个斜杠和后面的任何内容。
Answer from simple to more complex cases of the original question.
从原始问题的简单到更复杂的情况下回答。
If path is guaranteed to end without any slash (in and out)
如果路径保证结束没有任何斜线(进出)
P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
If path is guaranteed to end with exactly one slash (in and out)
如果保证路径以恰好一个斜杠(输入和输出)结尾
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
If input path may end with zero or one slash (not more) and you want output path to end without slash
如果输入路径可能以零或一个斜杠(不是更多)结尾,并且您希望输出路径以没有斜杠结尾
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/
do
P_ENDNOSLASH="${P%/}" ; echo "${P_ENDNOSLASH%/*}"
done
/home/smith/Desktop
/home/smith/Desktop
If input path may have many extraneous slashes and you want output path to end without slash
如果输入路径可能有很多多余的斜线,并且您希望输出路径没有斜线结束
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/ \
/home/smith///Desktop////Test//
do
P_NODUPSLASH="${P//\/*(\/)/\/}"
P_ENDNOSLASH="${P_NODUPSLASH%%/}"
echo "${P_ENDNOSLASH%/*}";
done
/home/smith/Desktop
/home/smith/Desktop
/home/smith/Desktop
回答by Marcelo Lacerda
Depending on whether you need absolute paths you may want to take an extra step:
根据您是否需要绝对路径,您可能需要采取额外的步骤:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
回答by Kaustubh
use this : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
if you want 4th parent directory
使用这个:export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
如果你想要第四个父目录
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
if you want 3rd parent directory
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
如果你想要第三个父目录
export MYVAR="$(dirname "$(dirname $PWD)")"
if you want 2nd parent directory
export MYVAR="$(dirname "$(dirname $PWD)")"
如果你想要第二个父目录
回答by magoofromparis
ugly but efficient
丑陋但高效
function Parentdir()
{
{
local lookFor_ parent_ switch_ i_
lookFor_=""
#if it is not a file, we need the grand parent
[ -f "$lookFor_" ] || switch_="/.."
#length of search string
i_="${#lookFor_}"
#remove string one by one until it make sens for the system
while [ "$i_" -ge 0 ] && [ ! -d "${lookFor_:0:$i_}" ];
do
let i_--
done
#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")"
#done
echo "
lookFor_:
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_
"
}
}
lookFor_: /home/Om Namah Shivaya
{lookFor_:0:6}: /home/
realpath {lookFor_:0:6}: /home
parent_: /home
lookFor_: /var/log
{lookFor_:0:8}: /var/log
realpath {lookFor_:0:8}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /var/log/
{lookFor_:0:9}: /var/log/
realpath {lookFor_:0:9}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /tmp//res.log/..
{lookFor_:0:6}: /tmp//
realpath {lookFor_:0:6}: /tmp
parent_: /
lookFor_: /media/sdc8/../sdc8/Debian_Master//a
{lookFor_:0:35}: /media/sdc8/../sdc8/Debian_Master//
realpath {lookFor_:0:35}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8//Debian_Master/../Debian_Master/a
{lookFor_:0:44}: /media/sdc8//Debian_Master/../Debian_Master/
realpath {lookFor_:0:44}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
{lookFor_:0:53}: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
realpath {lookFor_:0:53}: /media/sdc8/Debian_Master/For_Debian
parent_: /media/sdc8/Debian_Master
lookFor_: /tmp/../res.log
{lookFor_:0:8}: /tmp/../
realpath {lookFor_:0:8}: /
parent_: /
回答by kris
Started from the idea/comment Charles Duffy?- Dec 17 '14 at 5:32 on the topic Get current directory name (without full path) in a Bash script
从想法/评论 Charles Duffy?- 2014 年 12 月 17 日 5:32 开始,主题为在 Bash 脚本中获取当前目录名称(无完整路径)
#!/bin/bash
#INFO : https://stackoverflow.com/questions/1371261/get-current-directory-name-without-full-path-in-a-bash-script
# comment : by Charles Duffy?- Dec 17 '14 at 5:32
# at the beginning :
declare -a dirName[]
function getDirNames(){
dirNr="$( IFS=/ read -r -a dirs <<<"${dirTree}"; printf '%s\n' "$((${#dirs[@]} - 1))" )"
for(( cnt=0 ; cnt < ${dirNr} ; cnt++))
do
dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s\n' "${dirs[${#dirs[@]} - $(( $cnt+1))]}" )"
#information – feedback
echo "$cnt : ${dirName[$cnt]}"
done
}
dirTree=$PWD;
getDirNames;