Getting the parent of a directory in Bash
如果我有一个文件路径,比如…
1 2 | /home/smith/Desktop/Test /home/smith/Desktop/Test/ |
如何更改字符串使其成为父目录?
例如
1 2 | /home/smith/Desktop /home/smith/Desktop/ |
1 2 | dir=/home/smith/Desktop/Test parentdir="$(dirname"$dir")" |
如果有一个尾随斜杠也可以。
…但是"这里看到"的东西被破坏了。这里是修复:
1 2 3 4 5 6 7 8 | > pwd /home/me > x='Om Namah Shivaya' > mkdir"$x" && cd"$x" /home/me/Om Namah Shivaya > parentdir="$(dirname"$(pwd)")" > echo $parentdir /home/me |
显然,父目录是通过简单地附加点文件名给出的:
1 | /home/smith/Desktop/Test/.. # unresolved path |
但您必须要解析的路径(没有任何点路径组件的绝对路径):
1 | /home/smith/Desktop # resolved path |
使用
1 2 3 4 | $ dir=~/Library/../Desktop/../.. $ parentdir="$(dirname"$dir")" $ echo $parentdir /Users/username/Library/../Desktop/.. # not fully resolved |
这是更强大的:
1 2 | dir=/home/smith/Desktop/Test parentdir=`eval"cd $dir;pwd;cd - > /dev/null"` |
您可以使用
1 2 3 4 | $ dir=~/Library/../Desktop/../.. $ parentdir=`eval"cd $dir;pwd;cd - > /dev/null"` $ echo $parentdir /Users # the fully resolved path! |
只需使用
如果你想要的是
1 | dirname 'path/to/child/dir' |
如这里所见。
另一个答案的动机
我喜欢非常短、清晰、有保证的代码。如果它不运行一个外部程序,就可以获得额外的积分,因为在您需要处理大量条目的那天,它会明显更快。
原理不知道你有什么保证和想要什么,所以无论如何提供。
如果你有保证,你可以用很短的代码来完成。其思想是使用bash文本替换特性来剪切最后一个斜杠以及后面的内容。
回答从简单到复杂的原始问题。
如果保证路径结尾没有任何斜线(in和out)1 2 | P=/home/smith/Desktop/Test ; echo"${P%/*}" /home/smith/Desktop |
如果保证路径以一个斜杠结尾(in和out)
1 2 | P=/home/smith/Desktop/Test/ ; echo"${P%/*/}/" /home/smith/Desktop/ |
如果输入路径可能以零或一个斜杠(不是多个)结尾,并且希望输出路径以无斜杠结尾
1 2 3 4 5 6 7 8 9 | 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 |
如果输入路径可能有许多多余的斜线,并且您希望输出路径不带斜线而结束
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
如果需要第四个父目录,请使用:
根据您是否需要绝对路径,您可能需要采取额外步骤:
1 2 3 | child='/home/smith/Desktop/Test/' parent=$(dirname"$child") abs_parent=$(realpath"$parent") |
从14年12月17日5:32关于bash脚本中获取当前目录名(不带完整路径)的想法/评论开始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/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 '"$((${#dirs[@]} - 1))" )" for(( cnt=0 ; cnt < ${dirNr} ; cnt++)) do dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s '"${dirs[${#dirs[@]} - $(( $cnt+1))]}" )" #information – feedback echo"$cnt : ${dirName[$cnt]}" done } dirTree=$PWD; getDirNames; |
丑陋但有效率
1 | function Parentdir() |
{
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | local lookFor_ parent_ switch_ i_ lookFor_="$1" #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_: $1 {lookFor_:0:$i_}: ${lookFor_:0:$i_} realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_}) parent_: $parent_ " |
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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_: / |