$ 0変数を分割してbashのディレクトリと相対パスを見つけるにはどうすればよいですか?


10

$ 0変数には、スクリプトのパス情報が含まれています。

  • パス情報を絶対パスに変更するにはどうすればよいですか?〜、。、..、または類似の処理方法を意味しますか?
  • パス情報をディレクトリとファイル名に分割するにはどうすればよいですか?

これにはpython / perlを使用できますが、可能であればbashを使用したいと思います。


何を達成しようとしていますか?ところで。〜/ foo.shでスクリプトを呼び出すと、bashバージョン(GNU bash、バージョン4.1.5(2)-release-(x86_64-unknown-linux-gnu))で
echox

回答:


17

のようなものを処理する必要はありません~。シェルが処理します。これが~/filename、任意のスクリプトまたはプログラムに渡して機能する理由です。これらのプログラムはすべて~自分自身を処理せず、シェルが引数をに変換し、/home/username/filename代わりにプログラムに渡します。

$ echo ~/filename
/home/mrozekma/filename

正規のファイル名(などを含まないファイル名)が必要な場合は..realpathNeilに感謝)を使用します。

$ realpath ~/../filename
/home/filename

パスをディレクトリ名とファイル名に分割するには、andを使用dirnamebasenameます:

$ dirname /foo/bar/baz
/foo/bar

$ basename /foo/bar/baz
baz

リードリンクではなく、リアルパスを意味していると思います。readlinkは一般的な状況では機能しません。つまり、リンクが相対パスを使用していて、リンクと同じディレクトリにいない場合です。
ニールメイヒュー

@Neilのrealpath方が優れていますが、readlink試してみるとうまくいくようです。失敗する例を知っていますか?
マイケルMrozek

1
cd /tmp; touch foo; ln -s foo bar; cd; readlink /tmp/bar。これはfoorealpath返し/tmp/foo、が返されます。
Neil Mayhew

1
@ Neil、@ Michael:(readlink -f-f)はとほぼ同等でrealpath、より移植性があります。GNUcoreutilsでは、readlink -f他のいくつかのシステムにも存在します。realpath個別にパッケージ化されており、インストールされていない可能性があります(たとえば、Ubuntu 10.04またはDebian lennyでは、5つの一般的でないパッケージに依存しています)。
Gilles「SO-邪悪なことをやめなさい」11/10/13

@ギレス:良い点。realpath -fについてのリマインダーをありがとう。
Neil Mayhew 2010年

5

Michaelが述べたようにdirnameとbasenameを使用することは、必要なものを取得するための最も安全な方法です。

とにかく、本当に「bash only tools」でこれを実行したい場合は、パラメーター置換を使用できます。

echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.

この例は、一見に値するAdvanced Bash Scripting Guideから直接引用したものです。

説明は非常に簡単です:

$ {var#Pattern} $ varのフロントエンドと一致する$ Patternの最も短い部分を$ varから削除します。$ {var ## Pattern} $ varから、$ varのフロントエンドと一致する$ Patternの最も長い部分を削除します。

いくつかの正規表現のようなパターンとを見てください#または##貪欲/非貪欲修飾のいくつかの種類として。

これは、パスパーツのさらに複雑な抽出を行う必要がある場合に役立ちます。


5
使用する際に注意してください${...##...}と友人ではなく、dirnameそしてbasename、彼らはすべてのケースでは動作しません。たとえば、両方の${0##*/}${0%/*}同じに展開する$0場合は$0含まれていません/
Gilles「SO-邪悪になるのをやめる」

@Gillesはなぜ${0%/*}がに代わるものではないのか理解していdirnameます。ただし、${0##*/}代わりにを使用することの何が問題になっていbasenameますか?
toxalot 2014年

@toxalotこの場合、唯一の問題は$0、末尾にが付いたディレクトリ名である場合です/。しかし、私は私の助言を後悔しdirnameます。
Gilles「SO-邪悪なことをやめなさい」2014

2

realpath 実際のパスを通知するコマンドです(..およびシンボリックリンクなどを削除します)。

FreeBSDの標準です。この議論によると、それはLinuxでも利用可能です:

http://www.unix.com/shell-programming-scripting/89294-geting-real-path.html

その議論はbashソリューションも提供します:

$ bash -c "cd /foo/../bar/ ; pwd"

1
正確には、次のようなものが通常は機能します:MYDIR = "$(cd $(dirname" $ 0 "); pwd)"
Kevin Cantu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.