มีคำสั่ง Unix เพื่อรับเส้นทางสัมบูรณ์ (และ canonicalized) จากเส้นทางสัมพัทธ์ซึ่งอาจมีลิงค์สัญลักษณ์?
มีคำสั่ง Unix เพื่อรับเส้นทางสัมบูรณ์ (และ canonicalized) จากเส้นทางสัมพัทธ์ซึ่งอาจมีลิงค์สัญลักษณ์?
คำตอบ:
คุณสามารถใช้readlink
ยูทิลิตีพร้อม-f
ตัวเลือก:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
การแจกแจงบางอย่างเช่นผู้ที่ใช้core GNUUและFreeBSDก็มาพร้อมกับrealpath(1)
ยูทิลิตี้ที่โดยทั่วไปแล้วเพียงแค่เรียกrealpath(3)
และทำสิ่งเดียวกัน
readlink
มิได้realpath
- Solaris และ HP-UX โดยเฉพาะอย่างยิ่ง
brew install coreutils
apple.stackexchange.com/a/69332/23040และถ้าคุณไม่ต้องการที่จะทำขั้นตอนที่เปลี่ยนเส้นทางมาตรฐานเครื่องมือทั้งหมด Mac CLI ไปติดตั้งใหม่เทียบเท่า GNU greadlink
โทรเพียง
portably ที่PWD
ตัวแปรถูกกำหนดโดยเปลือกไปยังสถานที่หนึ่งที่แน่นอนของไดเรกทอรีปัจจุบัน องค์ประกอบใด ๆ ของเส้นทางนั้นอาจเป็นลิงก์สัญลักษณ์
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
หากคุณต้องการกำจัด.
และ..
เปลี่ยนไดเรกทอรีที่มีไฟล์และไปที่$PWD
นั่น:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
ไม่มีวิธีพกพาในการติดตามลิงก์สัญลักษณ์ หากคุณมีเส้นทางไปยังไดเรกทอรีจากนั้นส่วนใหญ่$(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
แสดงให้เห็นเส้นทางที่ไม่ได้ใช้ลิงก์สัญลักษณ์เพราะเปลือกหอยที่ติดตามลิงก์สัญลักษณ์มีแนวโน้มที่จะใช้pwd -P
("P" สำหรับ "ทางกายภาพ")
บาง Unices จัดให้มียูทิลิตี้ในการพิมพ์เส้นทาง "ทางกายภาพ" ไปยังไฟล์
readlink -f
เช่น FreeBSD .38.3, NetBSD ≥4.0, และ OpenBSD ไกลถึง 2.2realpath
(ยังมีอยู่ในระบบ Linux บางระบบและอยู่ใน BusyBox)หาก Perl สามารถใช้ได้คุณสามารถใช้โมดูลCwd
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
) ดูเหมือนจะไม่สนใจ stdin
||
คือpwd
เหมาะสำหรับความต้องการของคุณ มันให้เส้นทางที่แน่นอนของไดเรกทอรีปัจจุบัน หรืออาจจะเป็นสิ่งที่คุณต้องการคือrealpath ()
alister
และrss67
ในบทความนี้แนะนำวิธีที่เสถียรที่สุดเข้ากันได้และง่ายที่สุด ฉันไม่เคยเห็นวิธีที่ดีกว่านี้มาก่อน
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
หากคุณต้องการกลับไปที่ตำแหน่งเดิม
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
หรือ
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
ฉันหวังว่านี่จะช่วยได้ นี่เป็นทางออกที่ดีที่สุดสำหรับฉัน
ABSPATH=$(cd -- "$RELPATH" && pwd)
นี้: หมายเหตุเครื่องหมายอัญประกาศคู่รอบการแทน (เพื่อไม่ให้แตกถ้าพา ธ ประกอบด้วยช่องว่างและอักขระกลม) และ--
(ในกรณีที่พา ธ เริ่มต้นด้วย-
) นอกจากนี้ยังใช้งานได้เฉพาะกับไดเรกทอรีและไม่เชื่อมโยงสัญลักษณ์สัญลักษณ์ตามที่ร้องขอ ดูคำตอบของฉันสำหรับรายละเอียดเพิ่มเติม
คำตอบอื่น ๆ ที่นี่ก็ดี แต่ก็ไม่เพียงพอสำหรับความต้องการของฉัน ฉันต้องการโซลูชันที่ฉันสามารถใช้ในสคริปต์ของฉันในเครื่องใดก็ได้ ทางออกของฉันคือการเขียนเชลล์สคริปต์ที่ฉันสามารถเรียกใช้จากสคริปต์ที่ฉันต้องการ
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
โซลูชันนี้เขียนขึ้นสำหรับ Bourne Shell เพื่อความสะดวกในการพกพา ฉันมีสิ่งนี้ในสคริปต์ชื่อ "respath.sh"
สคริปต์นี้สามารถใช้ดังนี้:
respath.sh '/path/to/file'
หรือเช่นนี้
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
สคริปต์แก้ไขพา ธ ในอาร์กิวเมนต์แรกโดยใช้พา ธ จากอาร์กิวเมนต์ที่สองเป็นจุดเริ่มต้น หากมีเพียงอาร์กิวเมนต์แรกเท่านั้นสคริปต์จะแก้ไขพา ธ ที่สัมพันธ์กับไดเร็กทอรีการทำงานปัจจุบันของคุณ
pwd
builtin และไม่สนับสนุนการ-P
(บอร์นเชลล์ไม่ได้ดำเนินการตามที่ $ PWD ตรรกะจัดการเช่นเปลือกหอย POSIX ทำ)
cd -P --
เช่นเดียวกับในกรณีที่อาร์กิวเมนต์ที่ 1 มีบางส่วน ..
case
ตรวจสอบควรจะแทน..|../*)
..*
dirname $cwd
ในกรณีนอกจากนี้คุณมีเส้นทางที่กำหนดไว้ล่วงหน้าสำหรับ$1
(โดยปกติ${PWD}
) บางอย่างต่อไปนี้จะทำงาน:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
ฉันพบว่าฟังก์ชั่นด้านล่างนั้นง่ายและพกพาได้ระหว่าง linux / MAC OSX เมื่อเทียบกับคนอื่น ๆ ที่ฉันพบทุกที่ อาจช่วยใครซักคน
#!/usr/bin/bash
get_absolute_path(){
file_path=`pwd $1`
echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
สมมติว่าตัวแปรจัดเก็บชื่อพา ธ (a = "อะไรก็ตาม")
1.สำหรับเส้นทางที่มีพื้นที่ว่าง:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2.สำหรับคำถามจริงเช่นการแปลงพา ธ เป็นสัมบูรณ์: readlinkสามารถดึงเนื้อหา symlink ซึ่งสามารถใช้งานได้ดังต่อไปนี้ (หมายเหตุreadlink -f
จะสมบูรณ์ แต่ไม่มีใน Mac OS X อย่างน้อย bash ซึ่ง-fหมายถึงFORMATS )
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3.เพิ่งเรียนรู้pwd -P
ในman pwd
: -P คือ " แสดงไดเรกทอรีทำงานปัจจุบันทางกายภาพ (ลิงก์สัญลักษณ์ทั้งหมดได้รับการแก้ไข) " และด้วยเหตุนี้
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
จะทำงานด้วย
สรุป:รวม1กับ2เพื่อตอบสนองทั้งความต้องการของคุณในขณะที่พื้นที่ที่มีชื่อเส้นทางเป็นที่เรียบร้อยแล้วการดูแลในรัดกุมมากขึ้น3
-f
สวิทช์ไม่ได้อยู่บน Mac OS X (อย่างน้อย ณ 10.8.5) หากไม่มี-f
สวิตช์ก็แค่ส่งคืนรหัสข้อผิดพลาด