Nếu tôi có đường dẫn tệp như ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Làm thế nào để tôi thay đổi chuỗi để nó sẽ là thư mục cha?
ví dụ
/home/smith/Desktop
/home/smith/Desktop/
Nếu tôi có đường dẫn tệp như ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
Làm thế nào để tôi thay đổi chuỗi để nó sẽ là thư mục cha?
ví dụ
/home/smith/Desktop
/home/smith/Desktop/
Câu trả lời:
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Hoạt động nếu có một dấu gạch chéo, quá.
parentdir=$(dirname `pwd`)
... nhưng những gì "nhìn thấy ở đây " đã bị phá vỡ. Đây là cách khắc phục:
> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
Chỉ cần sử dụng echo $(cd ../ && pwd)
trong khi làm việc trong thư mục có thư mục cha bạn muốn tìm hiểu. Chuỗi này cũng có thêm lợi ích của việc không có dấu gạch chéo.
echo
ở đây.
Rõ ràng thư mục mẹ được đưa ra chỉ bằng cách nối thêm tên tệp dấu chấm:
/home/smith/Desktop/Test/.. # unresolved path
Nhưng bạn phải muốn đường dẫn được giải quyết (một đường dẫn tuyệt đối không có bất kỳ thành phần đường dẫn dấu chấm nào):
/home/smith/Desktop # resolved path
Vấn đề với các câu trả lời hàng đầu được sử dụng dirname
là chúng không hoạt động khi bạn nhập một đường dẫn có dấu chấm:
$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/.. # not fully resolved
Điều này mạnh hơn :
dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
Bạn có thể nuôi nó /home/smith/Desktop/Test/..
, nhưng cũng có những đường dẫn phức tạp hơn như:
$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users # the fully resolved path!
EDIT: Nếu nó không hoạt động, hãy kiểm tra xem bạn cd
đã không được sửa đổi chưa, như đôi khi là thông lệ,
$ which cd
cd is a function #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
builtin cd "$@";
ls -FGAhp
}
...
eval
KHÔNG tuyệt vời nếu có bất kỳ cơ hội phân tích cú pháp đầu vào của người dùng có thể đưa bạn đến một nơi nào đó mà bạn không mong đợi hoặc chạy những điều xấu đối với hệ thống của bạn. Bạn có thể sử dụng pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
thay vì eval
?
eval
gì cả: chỉ cần làm parentdir=$(cd -- "$dir" && pwd)
. Vì cd
được chạy trong một mạng con, bạn không cần phải cd
quay lại nơi chúng tôi đã ở. Đây --
là ở đây trong trường hợp mở rộng $dir
bắt đầu với một dấu gạch nối. Điều &&
này chỉ là để ngăn chặn parentdir
có một nội dung không trống khi cd
không thành công.
Tôi thích mã rất ngắn, rõ ràng, được đảm bảo. Điểm thưởng nếu nó không chạy một chương trình bên ngoài, vì ngày bạn cần xử lý một số lượng lớn các mục, nó sẽ nhanh hơn đáng kể.
Không chắc chắn về những gì đảm bảo bạn có và muốn, vì vậy cung cấp nào.
Nếu bạn có đảm bảo bạn có thể làm điều đó với mã rất ngắn. Ý tưởng là sử dụng tính năng thay thế văn bản bash để cắt dấu gạch chéo cuối cùng và bất cứ điều gì tiếp theo.
Trả lời từ các trường hợp đơn giản đến phức tạp hơn của câu hỏi ban đầu.
P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
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
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
${BASH_SOURCE[0]}
đó sẽ là đường dẫn đầy đủ đến tập lệnh nếu nó không có nguồn gốc thông qua source
hoặc .
.
Nếu /home/smith/Desktop/Test/../
là những gì bạn muốn:
dirname 'path/to/child/dir'
như đã thấy ở đây .
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. Mã liên kết cũng sai.
dirname Test
từ thư mục Test
đang ở.
Tùy thuộc vào việc bạn có cần đường dẫn tuyệt đối hay không, bạn có thể muốn thực hiện thêm một bước:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
dùng cái này : export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
nếu bạn muốn thư mục cha thứ 4
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
nếu bạn muốn thư mục cha thứ 3
export MYVAR="$(dirname "$(dirname $PWD)")"
nếu bạn muốn thư mục cha thứ 2
xấu nhưng hiệu quả
function Parentdir()
{
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_
"
}
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_: /
Bắt đầu từ ý tưởng / bình luận Charles Duffy - 17/12/14 lúc 5:32 về chủ đề Lấy tên thư mục hiện tại (không có đường dẫn đầy đủ) trong tập lệnh Bash
#!/bin/bash
#INFO : /programming/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;
nếu vì bất kỳ lý do gì bạn quan tâm đến việc điều hướng một số lượng thư mục cụ thể, bạn cũng có thể làm : nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Điều này sẽ cung cấp cho 3 thư mục cha mẹ lên
..
', nhưng có thể đó không hoàn toàn là những gì bạn nghĩ.