ファイルパスからファイルディレクトリパスを取得する


400

バッシュで、もしあるならVAR="/home/me/mydir/file.c"、どうすれば入手でき"/home/me/mydir"ますか?

回答:


649

dirnameそしてbasenameあなたは、パス成分を抽出するために探しているツールです。

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

これらは内部 Bashコマンドではありませんが、POSIX標準(、を参照)の一部であるためdirnamebasenameBashを実行するシステムの大部分で使用できるはずです。


4
変数名を括弧で囲み、 "$ VAR"ではないのはなぜですか?
user658182 2017

1
stackoverflow.com/questions/8748831/…は上記の質問に答えます。
user658182 2017

1
@ user658182この特定の例では、それは習慣ではなく、必要ではありません。
放棄されたカート

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

basenameとの依存関係を回避するにはdirname


3
どちらもPOSIXの一部であるため、依存関係は問題になりません。
orkoden 2013年

1
orkoden、あなたは正しい。私の回答の目的は、2つの追加プロセスを実行する義務がないことを示すことです。ユースケースにはbashで十分です。
Emmanuel Devaux 2013年

2
ファイル名またはフォルダー名を渡してからフォルダーパスを計算するため、エマニュエルの方法を使用しています。この正規表現を使用すると正しく動作しますが、フォルダーを入力すると、dirname関数は親フォルダーを返しました。
AnneTheAgile 2013

8
ただし、$ VARにパス情報がない場合、$ {VAR%/ *} / testは$ VAR / testと等しい予期しない値を生成しますが、$(dirname $ VAR)は./testの予測可能で適切な値を生成します。前者はファイル名をディレクトリとして扱い、後者は問題ないので、これは大きな問題です。
davemyron、2014年

19

関連する注意点として、ファイル名または相対パスしか持っていない場合は、それだけではdirname役に立ちません。私にとって、答えはになりましたreadlink

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

次に、2つを組み合わせてディレクトリのみを取得できます。

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
複数のパスコンポーネントが存在しない場合は、readlink -m "$fname"指定した名前を再帰的に正規化するために使用する必要があります
EDkan

7

ターゲットファイルをシンボリックリンクにする場合は、最初にそれをチェックして元のファイルを取得できます。以下のif句が役立つ場合があります。

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

私はこれで遊んでいて、代替案を考え出しました。

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

私が気に入った部分は、ツリーのバックアップを拡張するのが簡単だったことです。

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

これは、再帰的なトリミングに使用したスクリプトです。もちろん、$ 1を目的のディレクトリに置き換えます。

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

まず、/空のスペース()に置き換えました。次に、空白()の前のすべての文字を削除しました。最後に、空白の最初の文字()を削除しました。

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

ここで、new_path =でフルパスを取得します$(dirname ${BASH_SOURCE[0]})cd new_pathを使用して現在のディレクトリを変更し、次に実行pwdして現在のディレクトリへの完全パスを取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.