ฉันต้องการที่จะแปลง/foo/bar/..
เป็น/foo
มีคำสั่ง bash ซึ่งทำเช่นนี้?
แก้ไข: ในกรณีที่ปฏิบัติของฉันไดเรกทอรีที่มีอยู่
/foo/bar/..
เป็น/foo
และใช้bash
คำสั่ง หากมีข้อกำหนดอื่น ๆ ที่ไม่ได้ระบุไว้บางทีพวกเขาควรจะเป็น ...
ฉันต้องการที่จะแปลง/foo/bar/..
เป็น/foo
มีคำสั่ง bash ซึ่งทำเช่นนี้?
แก้ไข: ในกรณีที่ปฏิบัติของฉันไดเรกทอรีที่มีอยู่
/foo/bar/..
เป็น/foo
และใช้bash
คำสั่ง หากมีข้อกำหนดอื่น ๆ ที่ไม่ได้ระบุไว้บางทีพวกเขาควรจะเป็น ...
คำตอบ:
หากคุณต้องการที่จะ chomp ส่วนหนึ่งของชื่อไฟล์จากเส้นทาง "dirname" และ "basename" เป็นเพื่อนของคุณและ "realpath" ก็มีประโยชน์เช่นกัน
dirname /foo/bar/baz
# /foo/bar
basename /foo/bar/baz
# baz
dirname $( dirname /foo/bar/baz )
# /foo
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp
realpath
ทางเลือก
หากrealpath
เชลล์ของคุณไม่รองรับคุณสามารถลองใช้ได้
readlink -f /path/here/..
ด้วย
readlink -m /path/there/../../
ทำงานเหมือนกัน
realpath -s /path/here/../../
ในเส้นทางที่ไม่จำเป็นต้องอยู่ที่จะทำให้เป็นมาตรฐาน
realpath
และreadlink
มาจากยูทิลิตี้หลักของ GNU ดังนั้นส่วนใหญ่คุณอาจได้ทั้งหรือไม่ ถ้าฉันจำได้อย่างถูกต้องรุ่น readlink บน Mac นั้นจะแตกต่างจาก GNU เล็กน้อย: - \
ฉันไม่ทราบว่ามีคำสั่งทุบตีโดยตรงที่จะทำเช่นนี้ แต่ฉันมักจะทำ
normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"
และมันทำงานได้ดี
rm -rf $normalDir
) หากไม่มี dirToNormalize!
&&
ความคิดเห็นของ @ DavidBlevins
ลองrealpath
ดู ด้านล่างนี้เป็นแหล่งข้อมูลทั้งหมดขอบริจาคให้กับสาธารณสมบัติ
// realpath.c: display the absolute path to a file or directory.
// Adam Liss, August, 2007
// This program is provided "as-is" to the public domain, without express or
// implied warranty, for any non-profit use, provided this notice is maintained.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>
static char *s_pMyName;
void usage(void);
int main(int argc, char *argv[])
{
char
sPath[PATH_MAX];
s_pMyName = strdup(basename(argv[0]));
if (argc < 2)
usage();
printf("%s\n", realpath(argv[1], sPath));
return 0;
}
void usage(void)
{
fprintf(stderr, "usage: %s PATH\n", s_pMyName);
exit(1);
}
realpath
ส่วนที่เกี่ยวกับ นอกจากนี้ยังเป็นที่ชื่นชอบของฉัน แต่แทนที่จะรวบรวมเครื่องมือของคุณจากแหล่งที่มา มันคือทั้งหมดที่มีน้ำหนักมากและส่วนใหญ่เวลาที่คุณต้องการreadlink -f
... BTW readlink
ยังไม่ทุบตีในตัว แต่เป็นส่วนหนึ่งของcoreutils
Ubuntu
โซลูชันแบบพกพาและเชื่อถือได้คือการใช้ python ซึ่งติดตั้งล่วงหน้าแล้วในทุกที่ (รวมถึงดาร์วิน) คุณมีสองทางเลือก:
abspath
ส่งคืนพา ธ สัมบูรณ์ แต่ไม่สามารถแก้ไข symlink:
python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file
realpath
ส่งคืนพา ธ สัมบูรณ์และในการดำเนินการแก้ไข symlink สร้างพา ธ แบบบัญญัติ:
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file
ในแต่ละกรณีpath/to/file
สามารถเป็นเส้นทางแบบสัมพันธ์หรือแบบสัมบูรณ์
ใช้ยูทิลิตี readlink จากแพ็คเกจ coreutils
MY_PATH=$(readlink -f "$0")
readlink
เป็นมาตรฐานทุบตีสำหรับการได้รับเส้นทางที่แน่นอน นอกจากนี้ยังมีข้อได้เปรียบของการคืนค่าสตริงว่างหากไม่มีเส้นทางหรือเส้นทาง (ให้แฟล็กทำเช่นนั้น)
ในการรับพา ธ สัมบูรณ์ไปยังไดเร็กทอรีที่อาจมีหรือไม่มีอยู่ แต่มีใครเป็นผู้ปกครองให้ใช้:
abspath=$(readlink -f $path)
ในการรับพา ธ สัมบูรณ์ไปยังไดเร็กทอรีที่ต้องมีอยู่พร้อมกับพาเรนต์ทั้งหมด:
abspath=$(readlink -e $path)
หากต้องการกำหนดเส้นทางที่กำหนดและติดตาม symlink หากมีอยู่จริง แต่ไม่เช่นนั้นให้ข้ามไดเรกทอรีที่หายไปและกลับเส้นทางใหม่
abspath=$(readlink -m $path)
ข้อเสียเพียงอย่างเดียวคือ readlink จะติดตามลิงก์ หากคุณไม่ต้องการติดตามลิงก์คุณสามารถใช้ระเบียบปฏิบัติทางเลือกนี้:
abspath=$(cd ${path%/*} && echo $PWD/${path##*/})
ที่จะ chdir ไปยังส่วนไดเรกทอรีของ $ path และพิมพ์ไดเรกทอรีปัจจุบันพร้อมกับส่วนไฟล์ของ $ path หากล้มเหลวในการ chdir คุณจะได้รับสตริงว่างและข้อผิดพลาดใน stderr
readlink
เป็นตัวเลือกที่ดีถ้ามี เวอร์ชั่น OS X ไม่รองรับ-e
หรือ-f
ตัวเลือก ในสามตัวอย่างแรกคุณควรมีเครื่องหมายอัญประกาศคู่ล้อมรอบ$path
เพื่อจัดการช่องว่างหรือสัญลักษณ์แทนในชื่อไฟล์ +1 สำหรับการขยายพารามิเตอร์ แต่มีช่องโหว่ด้านความปลอดภัย หากpath
ว่างเปล่าสิ่งนี้จะcd
ไปยังไดเรกทอรีบ้านของคุณ คุณต้องมีเครื่องหมายคำพูดคู่ abspath=$(cd "${path%/*}" && echo "$PWD/${path##*/}")
คำถามเก่า แต่มีวิธีที่ง่ายกว่ามากถ้าคุณกำลังจัดการกับชื่อพา ธ แบบเต็มระดับเชลล์:
abspath = "$ (cd" $ path "&& pwd)"
เนื่องจาก cd เกิดขึ้นใน subshell จึงไม่มีผลกับสคริปต์หลัก
สองรูปแบบสมมติว่าคำสั่งในตัวเชลล์ของคุณยอมรับ -L และ -P คือ:
abspath = "$ (cd -P" $ path "&& pwd -P)" #physical path พร้อม symlink ที่ได้รับการแก้ไข abspath = "$ (cd -L" $ path "&& pwd -L)" #logical path รักษา symlink
โดยส่วนตัวแล้วฉันไม่ค่อยต้องการวิธีการนี้ในภายหลังเว้นแต่ฉันจะรู้สึกทึ่งกับลิงก์สัญลักษณ์ด้วยเหตุผลบางประการ
FYI: ความหลากหลายของการได้รับไดเรกทอรีเริ่มต้นของสคริปต์ที่ใช้งานได้แม้ว่าสคริปต์จะเปลี่ยนเป็นไดเรกทอรีปัจจุบันในภายหลัง
name0 = "$ (basename" $ 0 ")"; #base ชื่อของสคริปต์ dir0 = "$ (cd" $ (dirname "$ 0") "&& pwd)"; #absolute dir เริ่มต้น
การใช้ซีดีช่วยให้คุณมั่นใจได้ว่าจะมีไดเรกทอรีที่สมบูรณ์เสมอแม้ว่าสคริปต์จะถูกเรียกใช้โดยคำสั่งเช่น. /script.sh ซึ่งหากไม่มี cd / pwd มักจะให้เพียงแค่ .. ไร้ประโยชน์หากสคริปต์ใช้ซีดีในภายหลัง
อย่างที่อดัมลิสกล่าวไว้realpath
นั้นไม่ได้มาพร้อมกับการแจกทุกครั้ง ซึ่งเป็นความอัปยศเพราะมันเป็นทางออกที่ดีที่สุด ซอร์สโค้ดที่ให้มานั้นยอดเยี่ยมมากและฉันอาจจะเริ่มใช้งานได้ทันที นี่คือสิ่งที่ฉันใช้มาจนถึงตอนนี้ซึ่งฉันแบ่งปันที่นี่เพื่อความสมบูรณ์:
get_abs_path() {
local PARENT_DIR=$(dirname "$1")
cd "$PARENT_DIR"
local ABS_PATH="$(pwd)"/"$(basename "$1")"
cd - >/dev/null
echo "$ABS_PATH"
}
หากคุณต้องการให้ symlinks แก้ไขเพียงแทนที่ด้วยpwd
pwd -P
pwd -P
ตัวเลือกสำหรับกรณีนี้ ... พิจารณาว่าจะเกิดอะไรขึ้นถ้า$(basename "$1")
เป็น symlink ไปยังไฟล์ในไดเรกทอรีอื่น pwd -P
แก้ไขเพียง symlinks ในส่วนไดเรกทอรีของเส้นทาง แต่ไม่ได้ส่วน basename
ทางออกล่าสุดของฉันคือ:
pushd foo/bar/..
dir=`pwd`
popd
ตามคำตอบของ Tim Whitcomb
pushd $(dirname /usr/bin/java)
ลองได้
ไม่ใช่คำตอบที่แน่นอน แต่อาจเป็นคำถามติดตาม (คำถามเดิมไม่ชัดเจน):
readlink
ไม่เป็นไรถ้าคุณต้องการติดตาม symlinks แต่ยังมีกรณีการใช้งานสำหรับเพียง normalizing ./
และ../
และ//
ลำดับซึ่งสามารถทำได้อย่างหมดจดไวยากรณ์, โดยไม่ต้องกำลังยอมรับ symlinks readlink
ไม่ดีสำหรับสิ่งนี้และไม่เป็นrealpath
เช่นนั้น
for f in $paths; do (cd $f; pwd); done
ใช้งานได้สำหรับเส้นทางที่มีอยู่ แต่แบ่งให้ผู้อื่น
sed
สคริปต์ดูเหมือนจะเป็นทางออกที่ดียกเว้นว่าคุณไม่สามารถซ้ำเปลี่ยนลำดับ ( /foo/bar/baz/../..
-> /foo/bar/..
-> /foo
) โดยไม่ต้องใช้อะไรเช่น Perl ซึ่งไม่ปลอดภัยที่จะคิดในระบบทั้งหมดหรือใช้บางวงที่น่าเกลียดเพื่อเปรียบเทียบผลลัพธ์ของsed
การ อินพุตของมัน
FWIW หนึ่งซับในโดยใช้ Java (JDK 6+):
jrunscript -e 'for (var i = 0; i < arguments.length; i++) {println(new java.io.File(new java.io.File(arguments[i]).toURI().normalize()))}' $paths
realpath
มี-s
ตัวเลือกที่จะไม่สามารถแก้ไขการเชื่อมโยงสัญลักษณ์และมีเพียงการแก้ปัญหาการอ้างอิงถึง/./
, /../
และลบพิเศษ/
ตัวอักษร เมื่อรวมกับ-m
ตัวเลือกจะrealpath
ทำงานเฉพาะกับชื่อไฟล์และไม่ได้สัมผัสไฟล์จริงใด ๆ มันเสียงเหมือนโซลูชั่นที่สมบูรณ์แบบ แต่อนิจจาrealpath
ก็ยังขาดอยู่ในหลาย ๆ ระบบ
..
คอมโพเนนต์ไม่สามารถทำได้โดยใช้ syntactically เมื่อมีการเชื่อมโยง symlink /one/two/../three
ไม่เหมือนกันเช่น/one/three
ถ้าtwo
เป็น symlink /foo/bar
ไป
ฉันไปงานปาร์ตี้ช้า แต่นี่เป็นวิธีการแก้ปัญหาที่ฉันสร้างขึ้นหลังจากอ่านเธรดจำนวนมากเช่นนี้:
resolve_dir() {
(builtin cd `dirname "${1/#~/$HOME}"`'/'`basename "${1/#~/$HOME}"` 2>/dev/null; if [ $? -eq 0 ]; then pwd; fi)
}
สิ่งนี้จะแก้ไขเส้นทางที่แน่นอนของ $ 1 เล่นได้ดีกับ ~ เก็บ symlink ในเส้นทางที่พวกเขาอยู่และมันจะไม่ยุ่งกับสแต็คไดเรกทอรีของคุณ ส่งคืนพา ธ เต็มหรือไม่มีอะไรเลยหากไม่มีอยู่ คาดว่า $ 1 จะเป็นไดเรกทอรีและอาจล้มเหลวหากไม่ใช่ แต่นั่นเป็นการตรวจสอบที่ง่ายที่จะทำด้วยตัวเอง
ช่างพูดและตอบช้าไปหน่อย ฉันต้องเขียนมันตั้งแต่ฉันติดอยู่กับ RHEL4 / 5 ที่เก่ากว่า ฉันจัดการลิงก์ที่สมบูรณ์และสัมพัทธ์และลดความซับซ้อนของ //, /./ และ somedir /../
test -x /usr/bin/readlink || readlink () {
echo $(/bin/ls -l $1 | /bin/cut -d'>' -f 2)
}
test -x /usr/bin/realpath || realpath () {
local PATH=/bin:/usr/bin
local inputpath=$1
local changemade=1
while [ $changemade -ne 0 ]
do
changemade=0
local realpath=""
local token=
for token in ${inputpath//\// }
do
case $token in
""|".") # noop
;;
"..") # up one directory
changemade=1
realpath=$(dirname $realpath)
;;
*)
if [ -h $realpath/$token ]
then
changemade=1
target=`readlink $realpath/$token`
if [ "${target:0:1}" = '/' ]
then
realpath=$target
else
realpath="$realpath/$target"
fi
else
realpath="$realpath/$token"
fi
;;
esac
done
inputpath=$realpath
done
echo $realpath
}
mkdir -p /tmp/bar
(cd /tmp ; ln -s /tmp/bar foo; ln -s ../.././usr /tmp/bar/link2usr)
echo `realpath /tmp/foo`
ลองใช้ผลิตภัณฑ์real-lib- Bash ของห้องสมุด Bash ใหม่ที่เราวางไว้บน GitHub โดยไม่เสียค่าใช้จ่าย มันเป็นเอกสารอย่างละเอียดและทำให้เครื่องมือการเรียนรู้ที่ยอดเยี่ยม
จะแก้ไขเส้นทางท้องถิ่นญาติและแน่นอนและไม่มีการอ้างอิงใด ๆ ยกเว้น Bash 4+; ดังนั้นควรทำงานได้ทุกที่ ฟรีสะอาดเรียบง่ายและให้คำแนะนำ
คุณทำได้:
get_realpath <absolute|relative|symlink|local file path>
ฟังก์ชั่นนี้เป็นแกนหลักของห้องสมุด:
function get_realpath() {
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
นอกจากนี้ยังมีฟังก์ชั่นเพื่อ get_dirname, get_filename, get_ stemname และ validate_path ลองใช้ข้ามแพลตฟอร์มและช่วยในการปรับปรุง
ปัญหาrealpath
คือมันไม่สามารถใช้ได้ใน BSD (หรือ OSX สำหรับเรื่องนั้น) นี่เป็นสูตรง่าย ๆ ที่สกัดมาจากบทความที่ค่อนข้างเก่า (2009) จาก Linux Journalซึ่งค่อนข้างพกพา:
function normpath() {
# Remove all /./ sequences.
local path=${1//\/.\//\/}
# Remove dir/.. sequences.
while [[ $path =~ ([^/][^/]*/\.\./) ]]; do
path=${path/${BASH_REMATCH[0]}/}
done
echo $path
}
ขอให้สังเกตว่าตัวแปรนี้ยังไม่ต้องการเส้นทางที่มีอยู่
จากคำตอบของ @ Andre ฉันอาจมีเวอร์ชั่นที่ดีกว่าเล็กน้อยในกรณีที่มีใครบางคนอยู่หลังการแก้ปัญหาโดยใช้การจัดการสตริงแบบวนรอบ นอกจากนี้ยังเป็นประโยชน์สำหรับผู้ที่ไม่ต้องการที่จะ dereference symlinks ใด ๆ ซึ่งเป็นข้อเสียของการใช้หรือrealpath
readlink -f
มันใช้งานได้กับเวอร์ชั่นทุบตี 3.2.25 ขึ้นไป
shopt -s extglob
normalise_path() {
local path="$1"
# get rid of /../ example: /one/../two to /two
path="${path//\/*([!\/])\/\.\./}"
# get rid of /./ and //* example: /one/.///two to /one/two
path="${path//@(\/\.\/|\/+(\/))//}"
# remove the last '/.'
echo "${path%%/.}"
}
$ normalise_path /home/codemedic/../codemedic////.config
/home/codemedic/.config
hello/../world
(2) จุดในชื่อไฟล์/hello/..world
(3) จุดหลังจาก double-slash /hello//../world
(4) จุดก่อนหรือหลัง double-slash /hello//./world
หรือ /hello/.//world
(5) ผู้ปกครองหลังปัจจุบัน: /hello/./../world/
(6) ผู้ปกครอง หลังจากที่ผู้ปกครอง: /hello/../../world
ฯลฯ - บางเหล่านี้สามารถแก้ไขได้โดยใช้ห่วงที่จะทำให้การแก้ไขจนเส้นทางหยุดการเปลี่ยนแปลง (ลบdir/../
เช่นกัน /dir/..
ยกเว้น แต่ลบออกdir/..
จากตอนท้าย)
จากตัวอย่างของ python ยอดเยี่ยมของ loveborg ฉันเขียนสิ่งนี้:
#!/bin/sh
# Version of readlink that follows links to the end; good for Mac OS X
for file in "$@"; do
while [ -h "$file" ]; do
l=`readlink $file`
case "$l" in
/*) file="$l";;
*) file=`dirname "$file"`/"$l"
esac
done
#echo $file
python -c "import os,sys; print os.path.abspath(sys.argv[1])" "$file"
done
FILEPATH="file.txt"
echo $(realpath $(dirname $FILEPATH))/$(basename $FILEPATH)
สิ่งนี้ใช้ได้แม้ว่าไฟล์จะไม่มีอยู่ มันต้องการไดเรกทอรีที่มีไฟล์อยู่
realpath -e
ฉันต้องการโซลูชันที่จะทำทั้งสามอย่าง:
realpath
และreadlink -f
เป็น addonsไม่มีคำตอบใดที่มีทั้ง # 1 และ # 2 ฉันเพิ่ม # 3 เพื่อบันทึกคนอื่น ๆ จากการโกนจามรี
#!/bin/bash
P="${1?Specify a file path}"
[ -e "$P" ] || { echo "File does not exist: $P"; exit 1; }
while [ -h "$P" ] ; do
ls="$(ls -ld "$P")"
link="$(expr "$ls" : '.*-> \(.*\)$')"
expr "$link" : '/.*' > /dev/null &&
P="$link" ||
P="$(dirname "$P")/$link"
done
echo "$(cd "$(dirname "$P")"; pwd)/$(basename "$P")"
นี่คือกรณีทดสอบสั้น ๆ ที่มีช่องว่างที่บิดเบี้ยวในเส้นทางเพื่อออกกำลังกายการอ้างอิงอย่างเต็มที่
mkdir -p "/tmp/test/ first path "
mkdir -p "/tmp/test/ second path "
echo "hello" > "/tmp/test/ first path / red .txt "
ln -s "/tmp/test/ first path / red .txt " "/tmp/test/ second path / green .txt "
cd "/tmp/test/ second path "
fullpath " green .txt "
cat " green .txt "
ฉันรู้ว่านี่เป็นคำถามโบราณ ฉันยังคงเสนอทางเลือกอื่น เมื่อเร็ว ๆ นี้ฉันพบปัญหาเดียวกันและไม่พบคำสั่งที่มีอยู่และพกพาได้ ดังนั้นฉันจึงเขียนเชลล์สคริปต์ต่อไปนี้ซึ่งรวมถึงฟังก์ชั่นที่สามารถหลอกลวงได้
#! /bin/sh
function normalize {
local rc=0
local ret
if [ $# -gt 0 ] ; then
# invalid
if [ "x`echo $1 | grep -E '^/\.\.'`" != "x" ] ; then
echo $1
return -1
fi
# convert to absolute path
if [ "x`echo $1 | grep -E '^\/'`" == "x" ] ; then
normalize "`pwd`/$1"
return $?
fi
ret=`echo $1 | sed 's;/\.\($\|/\);/;g' | sed 's;/[^/]*[^/.]\+[^/]*/\.\.\($\|/\);/;g'`
else
read line
normalize "$line"
return $?
fi
if [ "x`echo $ret | grep -E '/\.\.?(/|$)'`" != "x" ] ; then
ret=`normalize "$ret"`
rc=$?
fi
echo "$ret"
return $rc
}
https://gist.github.com/bestofsong/8830bdf3e5eb9461d27313c3c282868c
ฉันสร้างฟังก์ชันเฉพาะในตัวเพื่อจัดการสิ่งนี้โดยมุ่งเน้นที่ประสิทธิภาพสูงสุดที่เป็นไปได้ (เพื่อความสนุกสนาน) มันไม่สามารถแก้ symlinks realpath -sm
ดังนั้นจึงเป็นพื้นเดียวกับ
## A bash-only mimic of `realpath -sm`.
## Give it path[s] as argument[s] and it will convert them to clean absolute paths
abspath () {
${*+false} && { >&2 echo $FUNCNAME: missing operand; return 1; };
local c s p IFS='/'; ## path chunk, absolute path, input path, IFS for splitting paths into chunks
local -i r=0; ## return value
for p in "$@"; do
case "$p" in ## Check for leading backslashes, identify relative/absolute path
'') ((r|=1)); continue;;
//[!/]*) >&2 echo "paths =~ ^//[^/]* are impl-defined; not my problem"; ((r|=2)); continue;;
/*) ;;
*) p="$PWD/$p";; ## Prepend the current directory to form an absolute path
esac
s='';
for c in $p; do ## Let IFS split the path at '/'s
case $c in ### NOTE: IFS is '/'; so no quotes needed here
''|.) ;; ## Skip duplicate '/'s and '/./'s
..) s="${s%/*}";; ## Trim the previous addition to the absolute path string
*) s+=/$c;; ### NOTE: No quotes here intentionally. They make no difference, it seems
esac;
done;
echo "${s:-/}"; ## If xpg_echo is set, use `echo -E` or `printf $'%s\n'` instead
done
return $r;
}
หมายเหตุ: ฟังก์ชั่นนี้ไม่ได้จัดการเส้นทางที่ขึ้นต้นด้วย//
เนื่องจากสองสแลชสองเท่าที่เริ่มต้นของเส้นทางเป็นพฤติกรรมที่กำหนดโดยการนำไปปฏิบัติ แต่ก็จัดการ/
, ///
และอื่น ๆ เพียงแค่ปรับ
ฟังก์ชั่นนี้ดูเหมือนว่าจะจัดการกับกรณีขอบทั้งหมดอย่างถูกต้อง แต่อาจมีบางอย่างที่ฉันไม่ได้จัดการ
ผลการดำเนินงานหมายเหตุ: เมื่อเรียกที่มีมากมายของข้อโต้แย้งabspath
วิ่ง 10x ช้ากว่าrealpath -sm
; เมื่อเรียกด้วยอาร์กิวเมนต์ตัวเดียวให้abspath
รัน> 110x เร็วกว่าrealpath -sm
บนเครื่องของฉันส่วนใหญ่เนื่องจากไม่ต้องการรันโปรแกรมใหม่ทุกครั้ง
ฉันค้นพบวันนี้ว่าคุณสามารถใช้stat
คำสั่งเพื่อแก้ไขเส้นทาง
ดังนั้นสำหรับไดเรกทอรีเช่น "~ / Documents":
คุณสามารถเรียกใช้สิ่งนี้:
stat -f %N ~/Documents
ในการรับเส้นทางแบบเต็ม:
/Users/me/Documents
สำหรับ symlink คุณสามารถใช้ตัวเลือกรูปแบบ% Y:
stat -f %Y example_symlink
ซึ่งอาจส่งคืนผลลัพธ์เช่น:
/usr/local/sbin/example_symlink
ตัวเลือกการจัดรูปแบบอาจแตกต่างกับ * NIX เวอร์ชันอื่น แต่สิ่งเหล่านี้ใช้ได้กับฉันใน OSX
stat -f %N ~/Documents
บรรทัดเป็นปลาชนิดหนึ่งสีแดง ... เปลือกของคุณจะถูกแทนที่~/Documents
ด้วย/Users/me/Documents
และstat
เป็นเพียงพิมพ์คำต่อคำโต้แย้ง
วิธีง่ายๆในการใช้node.js
:
#!/usr/bin/env node
process.stdout.write(require('path').resolve(process.argv[2]));
/foo/bar
หรือแม้กระทั่ง/foo
มีอยู่จริงหรือคุณสนใจเฉพาะในด้านการจัดการสตริงตามกฎชื่อพา ธ