দ্রষ্টব্য: আমি বিশ্বাস করি এটি একটি শক্ত, পোর্টেবল, রেডিমেড সলিউশন বলে বিশ্বাস করি, যা সেই কারণেই প্রায় দীর্ঘ ।
নীচে একটি সম্পূর্ণ পসিক্স-কমপ্লায়েন্ট স্ক্রিপ্ট / ফাংশন রয়েছে যেহেতু ক্রস প্ল্যাটফর্ম (ম্যাকোজেও কাজ করে, readlink
এখনও -f
10.12 (সিয়েরা) হিসাবে সমর্থন করে না ) - এটি কেবল পসিক্স শেল ভাষার বৈশিষ্ট্য এবং কেবল পসিক্স-কমপ্লায়েন্ট ইউটিলিটি কল ব্যবহার করে ।
এটি জিএনইউ'র (এর কঠোর সংস্করণ ) পোর্টেবল বাস্তবায়নreadlink -e
readlink -f
।
আপনি করতে পারেন চালানোর স্ক্রিপ্ট সঙ্গেsh
বা উৎস ফাংশন মধ্যে bash
, ksh
এবংzsh
:
উদাহরণস্বরূপ, কোনও স্ক্রিপ্টের অভ্যন্তরে আপনি চালনার স্ক্রিপ্টটিকে সত্যিকারের ডিরেক্টরি উত্সের জন্য সিমলিঙ্কগুলি সমাধান করার জন্য এটি ব্যবহার করতে পারেন:
trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink
স্ক্রিপ্ট / ফাংশন সংজ্ঞা:
এই উত্তরটি থেকে কৃতজ্ঞতার সাথে কোডটি মানিয়ে নেওয়া হয়েছিল ।
আমি এখানে একটি bash
বেসড স্ট্যান্ড-একা ইউটিলিটি সংস্করণও তৈরি করেছি , যা আপনি নোড.জেস ইনস্টলড থাকলে ইনস্টল করতে পারেন can
npm install rreadlink -g
#!/bin/sh
# SYNOPSIS
# rreadlink <fileOrDirPath>
# DESCRIPTION
# Resolves <fileOrDirPath> to its ultimate target, if it is a symlink, and
# prints its canonical path. If it is not a symlink, its own canonical path
# is printed.
# A broken symlink causes an error that reports the non-existent target.
# LIMITATIONS
# - Won't work with filenames with embedded newlines or filenames containing
# the string ' -> '.
# COMPATIBILITY
# This is a fully POSIX-compliant implementation of what GNU readlink's
# -e option does.
# EXAMPLE
# In a shell script, use the following to get that script's true directory of origin:
# trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`.
target=$1 fname= targetDir= CDPATH=
# Try to make the execution environment as predictable as possible:
# All commands below are invoked via `command`, so we must make sure that
# `command` itself is not redefined as an alias or shell function.
# (Note that command is too inconsistent across shells, so we don't use it.)
# `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not
# even have an external utility version of it (e.g, Ubuntu).
# `command` bypasses aliases and shell functions and also finds builtins
# in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for
# that to happen.
{ \unalias command; \unset -f command; } >/dev/null 2>&1
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too.
while :; do # Resolve potential symlinks until the ultimate target is found.
[ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
fname=$(command basename -- "$target") # Extract filename.
[ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/'
if [ -L "$fname" ]; then
# Extract [next] target path, which may be defined
# *relative* to the symlink's own directory.
# Note: We parse `ls -l` output to find the symlink target
# which is the only POSIX-compliant, albeit somewhat fragile, way.
target=$(command ls -l "$fname")
target=${target#* -> }
continue # Resolve [next] symlink target.
fi
break # Ultimate target reached.
done
targetDir=$(command pwd -P) # Get canonical dir. path
# Output the ultimate target's canonical path.
# Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
if [ "$fname" = '.' ]; then
command printf '%s\n' "${targetDir%/}"
elif [ "$fname" = '..' ]; then
# Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
# AFTER canonicalization.
command printf '%s\n' "$(command dirname -- "${targetDir}")"
else
command printf '%s\n' "${targetDir%/}/$fname"
fi
)
rreadlink "$@"
সুরক্ষার উপর একটি স্পর্শক:
জার্নো , command
একই নামটির কোনও উপন্যাস বা শেল ফাংশন দ্বারা বিল্টিন ছায়াবিভক্ত নয় তা নিশ্চিত করে ফাংশনটির প্রসঙ্গে একটি মন্তব্যে জিজ্ঞাসা করেছে:
যদি unalias
বা হয় unset
এবং [
এলিয়াস বা শেল ফাংশন হিসাবে সেট করা হয়?
এর আসল অর্থ রয়েছে কিনা তা rreadlink
নিশ্চিত করার পিছনে অনুপ্রেরণা command
হ'ল এটিকে ব্যবহারের (সৌম্য) সুবিধাগুলি বাইপাস এবং ফাংশনগুলি প্রায়শই ইন্টারেক্টিভ শেলগুলিতে স্ট্যান্ডার্ড কমান্ডের ছায়া হিসাবে ব্যবহৃত হয়, যেমন ls
পছন্দসই বিকল্পগুলি অন্তর্ভুক্ত করার জন্য পুনরায় সংজ্ঞায়িত করা।
আমার মনে হয় এটা বলতে চাই যে কোনো অবিশ্বস্ত, দূষিত পরিবেশ সাথে এসেছেন ডিলিং যদি না আপনি প্রায় উদ্বেজক নিরাপদ unalias
বা unset
- বা, যে বিষয়টি জন্য, while
, do
একটি উদ্বেগের বিষয় নতুনভাবে সংজ্ঞায়িত করা হচ্ছে না -, ...।
এমন কিছু আছে যা ফাংশনটির অবশ্যই তার আসল অর্থ এবং আচরণের উপর নির্ভর করতে পারে - এর আশেপাশে কোনও উপায় নেই।
পসিক্স-এর মতো শেলগুলি বিল্টিনগুলির পুনরায় সংজ্ঞায়নের অনুমতি দেয় এবং ভাষার কীওয়ার্ডগুলি অন্তর্নিহিত একটি সুরক্ষা ঝুঁকি (এবং প্যারানয়েড কোড লেখার পক্ষে সাধারণভাবে কঠোর)।
আপনার উদ্বেগকে বিশেষভাবে সমাধান করতে:
ফাংশন নির্ভর করে unalias
এবং unset
তাদের আসল অর্থ রাখে। তাদের শেল ফাংশন হিসাবে এমনভাবে পুনরায় সংজ্ঞায়িত করা যাতে তাদের আচরণের পরিবর্তন ঘটে; একটি হিসাবে redefinition ওরফে না অগত্যা একটি উদ্বেগের বিষয়, কারণ মূল্য উদ্ধৃতি (অংশ) কমান্ড নাম (যেমন, \unalias
) alias লেখা রোধ করা যাবে।
যাইহোক, মূল্য উদ্ধৃতি হয় না শেল জন্য একটি বিকল্প কীওয়ার্ড ( while
, for
, if
, do
, ...) এবং শেল কীওয়ার্ড শেল বেশি প্রাধান্য গ্রহণ না যখন ফাংশন , ইন bash
এবং zsh
alias লেখা তাই শেল-শব্দ redefinitions আপনি চালাতে হবে সতর্ক, সর্বোচ্চ প্রাধান্য আছে unalias
সঙ্গে তাদের নামগুলি (যদিও অ-ইন্টারেক্টিভ bash
শেলগুলিতে (যেমন স্ক্রিপ্ট হিসাবে) এলিয়াসগুলি ডিফল্টরূপে প্রসারিত হয় না - তবে কেবল shopt -s expand_aliases
প্রথমে স্পষ্টভাবে বলা হয়)।
unalias
একটি বিল্টিন হিসাবে - এর আসল অর্থ রয়েছে তা নিশ্চিত করার জন্য আপনাকে \unset
প্রথমে এটি ব্যবহার করতে হবে , যার প্রয়োজন unset
এর মূল অর্থ:
unset
এটি একটি শেল অন্তর্নির্মিত , যাতে এটি যেমন প্রেরিত হয় তা নিশ্চিত করার জন্য, আপনাকে নিশ্চিত করতে হবে যে এটি নিজেই কোনও ফাংশন হিসাবে পুনরায় সংজ্ঞায়িত হয়নি । আপনি উদ্ধৃতি দিয়ে একটি উপনাম ফর্মটি বাইপাস করতে পারবেন, আপনি শেল-ফাংশন ফর্মটি বাইপাস করতে পারবেন না - 22 ধরুন।
সুতরাং, যতক্ষণ না আপনি unset
তার মূল অর্থের উপর নির্ভর করতে পারবেন না, আমি যা বলতে পারি তা থেকে, সমস্ত দূষিত পুনর্নির্ধারার বিরুদ্ধে রক্ষার কোনও গ্যারান্টিযুক্ত উপায় নেই।