readlink
シンボリックリンクを使用して一般的なファイルを取得する方法を知ることもできます。$@
私の関数に渡されたシンボリックリンクを次のように置き換える非常に基本的なアイデアがあります。
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f "$file")
done
たとえば、SymLinkです/etc/os-release -> ../usr/lib/os-release
。
しかし、これを行うと:
set -- '/etc/os-release'; for file in "$@"; do [ -L "$file" ] && file=$(readlink -f "$file"); done; echo "$@"
それでも元のSymLinkパスを取得できますが、これは残念です。自分で修正したいのですが、$@
不可能な場合は解決策はありませんか?
答え1
オリジナルコード:
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f -- "$file")
done
問題は、file
ループ内の設定が位置引数リストの内容に影響を与えないことです。
代わりに、以下を使用したい場合があります。
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f -- "$file")
set -- "$@" "$file"
shift
done
それでは、アイテムを最初から1つずつ削除"$@"
し、潜在的に変更されたアイテムをリストの後ろに追加します。ループ$@
内のfor
修正は、ループが常に静的リストを繰り返すので$@
問題ではありませんfor
。つまり、反復リストはループの開始時に一度だけ評価されます。
下のループと同様に、上のループは各反復ごとに位置パラメータの完全なリストをリセットします。一つのために巨大なファイル名のリストが遅すぎる可能性があります。シェルに配列がある場合、Steven Kitの答え作業速度を上げる方法を示します。
ループは少し短い形式(readlink
各要素ごとに呼び出されます)で書くこともできます。
for dummy do
set -- "$@" "$(readlink -f -- "$1")"
shift
done
readlink
これはPOSIXユーティリティではなくてもあなたの質問に従って使用されます。
参考として出力される場合readlink
1つ以上の改行で終わります(出力の最後の行を終了するために追加された内容を除いて)削除されます。これはコマンド置換の結果です。これが問題の場合は、コマンド置換に末尾の文字を人為的に追加し、提案どおりにmosvy
削除します。コメントから:
for file do
[ -L "$file" ] && file=$(readlink -f -- "$file"; echo x)
set -- "$@" "${file%x}"
shift
done
答え2
POSIXコマンドは両方ともではreadlink
ありません。 POSIXコマンドラインツールボックスには同様のAPIはrealpath
ありません。ここでは、同様の機能とその修飾子が組み込まれているものをrealpath()
代わりに使用できますreadlink
(互換性のない他の実装があります)。スクリプトから:zsh
realpath()
:P
sh
eval "set -- $(zsh -c 'print -r ${(qq)argv:P}' zsh "$@")"
zsh
スクリプトを最初に作成することもできますが、次のようにする必要があります。
argv=($argv:P)
それともpython3
zshよりも便利ですか?
eval "set -- $(
LC_ALL=C python3 -c '
import sys, os, shlex
print(" ".join(map(shlex.quote, map(os.path.realpath, sys.argv[1:]))))' "$@")"