質問:どちらのファイルを絶対パスで表示するための簡単なsh/bash/zsh/fish/...コマンドがありますか?
使用例:ディレクトリ/a/b
にいて、ファイルc
へのフルパスをコマンドラインに出力して、別のプログラムに貼り付けることができるようにします。/a/b/c
。これを実行するための単純でありながら小さなプログラムであれば、長いパスを処理することになると、おそらく5秒程度節約できます。だから私はこれを行うための標準的なユーティリティを見つけることができないことを驚かせます - 本当に何もありませんか?
これがabspath.pyのサンプル実装です。
#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
realpath
を試してください。
$ realpath example.txt
/home/username/example.txt
シンボリックリンクを解決するreadlink
を試してください。
readlink -e /foo/bar/baz
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
あなたのシステムにインストールされているかもしれないしインストールされていないかもしれないreadlink
とrealpath
については忘れてください。
上記のdogbaneの答えを展開すると、関数として表されます。
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
あなたはそれからこのようにそれを使うことができます:
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
この解決策は、Bash組み込みのpwd
コマンドが引数なしで呼び出されたときに現在のディレクトリの絶対パスを表示するという事実を利用します。
移植性があり、特定のLinux/Unixディストリビューションのデフォルトインストールには存在しないことが多いreadlink
もrealpath
も必要ありません。
上記のように、与えられたディレクトリパスが存在しない場合、関数は失敗してstderrに出力します。これはあなたが望むものではないかもしれません。その状況に対処するために関数を拡張することができます。
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
親ディレクトリが存在しない場合は、空の文字列を返します。
まあ、それはその場合絶対パスを与えますが、最小のものではありません。それは次のようになります。
/Users/bob/Documents/..
'..'を解決したい場合は、次のようにスクリプトを作成する必要があります。
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
Elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
$ readlink -m FILE
/path/to/FILE
ファイルが存在しなくても機能するので、これはreadlink -e FILE
またはrealpath
より優れています。
絶対パスコンバータへのこの相対パスシェル関数
cd
とpwd
のみ)..
と.
を処理しますコード:
function abspath() {
# generate absolute path from relative path
# $1 : relative filename
# return : absolute path
if [ -d "$1" ]; then
# dir
(cd "$1"; pwd)
Elif [ -f "$1" ]; then
# file
if [[ $1 = /* ]]; then
echo "$1"
Elif [[ $1 == */* ]]; then
echo "$(cd "${1%/*}"; pwd)/${1##*/}"
else
echo "$(pwd)/$1"
fi
fi
}
サンプル:
# assume inside /parent/cur
abspath file.txt => /parent/cur/file.txt
abspath . => /parent/cur
abspath .. => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir => /parent/dir # anything cd can handle
abspath doesnotexist => # empty result if file/dir does not exist
abspath /file.txt => /file.txt # handle absolute path input
注:これは、 from nolan60 および bsingh の回答に基づいていますが、ファイルの大文字と小文字は区別されます。
最初の質問は既存のコマンドラインユーティリティに関するものであることも理解しています。しかし、これは最小限の依存関係を持ちたいシェルスクリプトを含むスタックオーバーフローの問題であるように思われるので、このスクリプトソリューションをここに置くと、後で見つけることができます:)
find
コマンドが役に立つかもしれません
find $PWD -name ex*
find $PWD -name example.log
現在のディレクトリ以下のすべてのファイルをパターンに一致する名前で一覧表示します。ほんの少しの結果しか得られない場合は単純化できます(例:ファイルが少ないツリーの一番下のディレクトリ)
find $PWD
私はSolaris 10でこれを使用していますが、他のユーティリティは言及されていません。
もしあなたがreadlinkやrealpathユーティリティを持っていないのであれば、bashとzshで動く次の関数を使うことができます(残りについてはよくわからない)。
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
これは存在しないファイルに対しても機能します(python関数os.path.abspath
と同様に)。
残念ながらabspath ./../somefile
はドットを取り除きません。
これが私がそのコンパクトさのために好きであるzshだけの機能です。それは 'A'拡張修飾子を使います - zshexpn(1)を見てください。
realpath() { for f in "$@"; do echo ${f}(:A); done }
ファイルへのabsolute path
のようなものは一般的にはありません(このステートメントは、一般的に複数のものがあることを意味します。したがって、定冠詞を使用しますは適切ではありません)。 absolute path
は、ルート "/"から始まる任意のパスで、作業ディレクトリとは関係なく、あいまいさのないファイルを指定します(たとえば、 Wikipedia を参照)。
relative path
は、他のディレクトリから開始して解釈されるパスです。アプリケーションによって操作されているrelative path
の場合は、作業ディレクトリになる可能性があります(必ずしもそうとは限りません)。それがディレクトリ内のシンボリックリンクにあるとき、それは一般的にそのディレクトリに相対的であることを意図しています(ユーザは他の用途を念頭に置いているかもしれませんが)。
したがって、絶対パスは単にルートディレクトリからの相対パスです。
パス(絶対パスまたは相対パス)には、シンボリックリンクが含まれている場合と含まれていない場合があります。もしそうでなければ、それはまたリンク構造の変化に対して幾分不透過性であるが、これは必ずしも必要ではないかまたは望ましくさえない。 canonical path
(またはcanonical file name
またはresolved path
)を、すべてのシンボリックリンクが解決された、つまりリンク先のパスに置き換えられたabsolute path
と呼ぶ人もいます。コマンドrealpath
とreadlink
はどちらも正規のパスを探しますが、realpath
だけがシンボリックリンクを解決するために迷惑をかけずに絶対パスを取得するためのオプションを持っています。絶対パスまたは何らかのディレクトリに対する相対パス。
これにはいくつかの注意が必要です。
realpath
とreadlink
には、それを考慮するオプションがあります。canonical
ではなくなったことを意味します。したがって、この概念は時間(または環境)に依存します。canonical path
があるかもしれません:ro
)。したがって、canonical path
のより限定的な定義でも、ファイルへの正規のパスがいくつかあるかもしれません。これはまた、修飾子canonical
が通常一意性の概念を意味するため、やや不適切であることを意味します。
これは で他の似たような質問に対する答えの中でトピックの簡単な議論を拡張します:与えられた相対的な絶対パスを検索する
私の結論は、realpath
はreadlink
よりも優れて設計され、はるかに柔軟であるということです。 readlink
でカバーされていないrealpath
の唯一の使用法は、シンボリックリンクの値を返すオプションなしの呼び出しです。
dogbane
答え と説明が入っています。
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
説明:
"$1"
dirname "$1"
cd "$(dirname "$1")
し、pwd
シェルコマンドを実行して絶対パスを取得します。$(basename "$1")
echo
にします。これは質問に対する答えではありませんが、スクリプトを書く人のためのものです。
echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`
/ .. ./などを正しく処理します。私もOSXで動いているようです
ディレクトリの場合、dirname
は../
を取得して./
を返します。
nolan6000の関数 はそれを修正するために修正することができます。
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
私は自分のシステムに次のスクリプトを配置しました。現在のディレクトリにあるファイルへのフルパスをすばやく取得したい場合は、bashエイリアスと呼びます。
#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"
理由はわかりませんが、OS Xでスクリプト「$ PWD」を呼び出すと絶対パスに展開されます。 findコマンドがコマンドラインで呼び出されても、実行されません。しかし、それは私が欲しいものです...楽しんでください。
#! /bin/bash
file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')
これはrealpath
の欠点を補い、シェルスクリプトfullpath
に格納します。あなたは今呼び出すことができます:
$ cd && touch a\ a && rm A 2>/dev/null
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.
Rubyで絶対パスを取得するための代替手段:
realpath() {Ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
引数として引数なし(現在のフォルダ)、相対パス、絶対パス、またはフォルダパスを指定して動作します。