macos - مشكلة - لا يمكن العثور على ملف البرنامج النصي




باش البرنامج النصي المسار المطلق مع OS X (7)

realpath لنظام التشغيل Mac OS X

realpath() {
    path=`eval echo "$1"`
    folder=$(dirname "$path")
    echo $(cd "$folder"; pwd)/$(basename "$path"); 
}

مثال مع المسار ذي الصلة:

realpath "../scripts/test.sh"

مثال مع مجلد المنزل

realpath "~/Test/../Test/scripts/test.sh"

أحاول الحصول على المسار المطلق للنصي قيد التشغيل حاليًا على OS X.

رأيت العديد من الردود الذهاب readlink -f $0 . ومع ذلك ، بما أن نظام OS X هو نفس موقع BSD ، فهو لا يعمل (إنه يعمل مع إصدار GNU).

هل هناك حل خارج هذا الصندوق؟


أكثر متغير من الخطوط الجوية لحل بايثون:

python -c "import os; print(os.path.realpath('$1'))"

بما أن هناك realpath كما أشار آخرون:

// realpath.c
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char* argv[])
{
  if (argc > 1) {
    for (int argIter = 1; argIter < argc; ++argIter) {
      char *resolved_path_buffer = NULL;
      char *result = realpath(argv[argIter], resolved_path_buffer);

      puts(result);

      if (result != NULL) {
        free(result);
      }
    }
  }

  return 0;
}

ماكيفيلي:

#Makefile
OBJ = realpath.o

%.o: %.c
      $(CC) -c -o [email protected] $< $(CFLAGS)

realpath: $(OBJ)
      gcc -o [email protected] $^ $(CFLAGS)

ثم قم بالتجميع مع وضع ووضع رابط لين مع:
ln -s $(pwd)/realpath /usr/local/bin/realpath


حتى كما ترون أعلاه ، أخذت لقطة في هذا قبل حوالي 6 أشهر. لقد نسيت تماما عن ذلك حتى وجدت نفسي بحاجة إلى شيء مماثل مرة أخرى. لقد صدمت تمامًا عندما رأيت كيف كانت بدائية ؛ لقد كنت أقوم بتدريس نفسي بشكل مكثف منذ حوالي عام ، لكنني غالباً ما أشعر أنني ربما لم أتعلم أي شيء على الإطلاق عندما تكون الأمور في أسوأ حالاتها.

أود أن أزيل "الحل" أعلاه ، لكني أحب فعلاً نوعًا من كونه سجلًا لمدى معرفتي بالفعل خلال الأشهر القليلة الماضية.

لكنني استطرادا. جلست وعملت كل شيء في الليلة الماضية. يجب أن يكون التفسير في التعليقات كافياً. إذا كنت ترغب في تتبع النسخة التي أستمر في العمل عليها ، فيمكنك اتباع هذه البيانات. هذا ربما يفعل ما تحتاجه.

#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.

## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.

## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).

## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.

## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.

## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.

## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)

## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.

## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.

##===-------------------------------------------------------------------===##

for argv; do :; done # Last parameter on command line, for options parsing.

## Error messages. Use functions so that we can sub in when the error occurs.

recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "[email protected]"\n" ;} # Borrow a horrible signal name.

# Probably best not to install as 'pathfull', if you can avoid it.

pathfull(){ cd "$(dirname "[email protected]")"; link="$(readlink "$(basename "[email protected]")")"

## 'test and 'ls' report different status for bad symlinks, so we use this.

 if [ ! -e "[email protected]" ]; then if $(ls -d "[email protected]" 2>/dev/null) 2>/dev/null;  then
    errnoent 1>&2; exit 1; elif [ ! -e "[email protected]" -a "$link" = "[email protected]" ];   then
    recurses 1>&2; exit 1; elif [ ! -e "[email protected]" ] && [ ! -z "$link" ]; then
    dangling 1>&2; exit 1; fi
 fi

## Not a link, but there might be one in the path, so 'cd' and 'pwd'.

 if [ -z "$link" ]; then if [ "$(dirname "[email protected]" | cut -c1)" = '/' ]; then
   printf "[email protected]\n"; exit 0; else printf "$(pwd)/$(basename "[email protected]")\n"; fi; exit 0
 fi

## Walk the symlinks back to the origin. Calls itself recursivly as needed.

 while [ "$link" ]; do
   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
   case "$newlink" in
    "$link") dangling 1>&2 && exit 1                                       ;;
         '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
          *) link="$newlink" && pathfull "$link"                           ;;
   esac
 done
 printf "$(pwd)/$(basename "$newlink")\n"
}

## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".

if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"

# Yay ANSI l33t codes! Fancy.
 printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
 printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
 printf " From within an invocation of a script, locate the script's "
 printf "own file\n         (no matter where it has been linked or "
 printf "from where it is being called).\n\n"

else pathfull "[email protected]"
fi

قرف. لقد وجدت أن الإجابات السابقة ترغب قليلاً في بعض الأسباب: على وجه الخصوص ، فهي لا تحل مستويات متعددة من الروابط الرمزية ، وهي غاية "Bash-y". في حين أن السؤال الأصلي يطالب بصراحة بـ "Bash script" ، فإنه يشير أيضًا إلى ما يشبه BSD-like ، غير GNU. إذن ، هذه محاولة في بعض قابلية النقل المعقولة (لقد قمت بفحصها باستخدام bash كـ "sh" و "dash") ، وحل عددًا عشوائيًا من الروابط الرمزية ؛ ويجب أن تعمل أيضًا مع المسافات البيضاء في المسار (المسارات) ، على الرغم من أنني لست متأكدًا من السلوك إذا كان هناك مساحة بيضاء اسم القاعدة للمنشأة نفسها ، فربما ، أم ، تجنب ذلك؟

#!/bin/sh
realpath() {
  OURPWD=$PWD
  cd "$(dirname "$1")"
  LINK=$(readlink "$(basename "$1")")
  while [ "$LINK" ]; do
    cd "$(dirname "$LINK")"
    LINK=$(readlink "$(basename "$1")")
  done
  REALPATH="$PWD/$(basename "$1")"
  cd "$OURPWD"
  echo "$REALPATH"
}
realpath "[email protected]"

نأمل أن يكون من بعض الاستخدام لشخص ما.


كنت أبحث عن حل للاستخدام في البرنامج النصي توفير النظام ، أي ، تشغيل حتى يتم تثبيت حتى البيرة. إذا كنت تفتقر إلى حل مناسب ، فما استقاموا لكم فاستقيموا لتوه هذه المهمة إلى لغة عبر منصة ، على سبيل المثال ، بيرل:

script_abspath=$(perl -e 'use Cwd "abs_path"; print abs_path(@ARGV[0])' -- "$0")

في كثير من الأحيان ما نريده بالفعل هو الدليل المحتوي:

here=$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "$0")

على أساس التواصل مع المعلق ، وافقت على أنه من الصعب جدا وليس لديه وسيلة سهلة لتنفيذ سلوك يتصرف تماما نفس Ubuntu.

ولكن الإصدار التالي ، يمكن التعامل مع الحالات الزاوية أفضل إجابة لا يمكن تلبية احتياجاتي اليومية على ماك بوك. ضع هذا الكود في ~ / .bashrc وتذكر:

  • يمكن أن يكون arg ملفًا واحدًا أو dir فقط ، بدون حرف بدل
  • لا مسافات في dir أو اسم الملف
  • على الأقل الملف أو dir dir الأصلي موجود
  • لا تتردد في استخدامها. .. / شيء ، هذه آمنة
    # 1. if is a dir, try cd and pwd
    # 2. if is a file, try cd its parent and concat dir+file
    realpath() {
     [ "$1" = "" ] && return 1

     dir=`dirname "$1"`
     file=`basename "$1"`

     last=`pwd`

     [ -d "$dir" ] && cd $dir || return 1
     if [ -d "$file" ];
     then
       # case 1
       cd $file && pwd || return 1
     else
       # case 2
       echo `pwd`/$file | sed 's/\/\//\//g'
     fi

     cd $last
    }




path