2016-11-20 14 views
2

ファイルの親ディレクトリを取得するにはどうすればよいですか?bashでファイルの親ディレクトリを取得

私はそれが名前のすべての種類に安全になりたい:

. 
.. 
path/to/my/file 
/absolute/path/to/my/file 
'-rf --no-preserve-root whatever'/test.zip 
(symbolic links) 
`'"`'{(}) 

私は、ファイル名に記載されたパスを横断するよりも、ファイルシステム上の正規の位置を取得し、より興味を持っています。

がこれと同様の問題があるが、それらのどれも正確、相対的/絶対パスと "安全でない" の名前に焦点を当てていないことに注意してください:

[1] bash get the parent directory of current directory

[2] Retrieve parent directory of script

[3] bash filepath to parent directory of file

+1

ファイルを含むディレクトリのフルパス名、またはファイルを含むディレクトリの親ディレクトリを探していますか?あなたは、ファイル名に記載されたパスをたどることに興味がありますか?あるいは、ファイルシステム上の正式な場所を取得することに興味がありますか? – ghoti

+0

両方の質問の2番目のケース。 – VasyaNovikov

+0

現在のディレクトリが '/ home/user/bin'で、'ファイル名 'が '..'(親のカレントディレクトリ)であるとします。おそらく、そのエントリを含むディレクトリは '/ home/user/bin'なので、親ディレクトリは'/home/user'か、他の解釈が必要です(ディレクトリ '..'は'/home/user'です。親ディレクトリは '/ home'です)。私は '仮定された'変種が正しいと思っていますし、 '.'と同様ですが、チェックするのも良いでしょう。 –

答えて

6

本当に安全なソリューション:

parent_dir="$(dirname -- "$(realpath -- "$file_name")")" 
お使いのシステムが realpathを持っていませんが、 readlinkを持っていない場合は

が、これは動作するはずです:

parent_dir="$(dirname -- "$(readlink -f -- "$file_name")")" 
+0

これはbashの質問でした。私は、OS X、FreeBSD、およびあなたが提案している 'realpath'コマンドを持たないLinuxではない他のオペレーティングシステム上でbashを使用します。これはbashの一部ではありません。私が管理するLinuxシステムでさえ、 'realpath'は利用可能ですが、デフォルトではインストールされません。特定のプラットフォームでのみ動作するものを提案する必要があると感じる場合は、少なくともプラットフォームを言及してください。 – ghoti

+1

@ghoti FreeBSDには、['realpath(1)'](https://www.freebsd.org/cgi/man.cgi?query=realpath)ユーティリティがあります。 「realpathユーティリティは、FreeBSD 4.3ではじめて登場しました。 – kdhp

+1

@kdhp:macOS Sierra(およびその前のMac OS X)はBSDから派生していますが、デフォルトでは 'realpath'コマンドは含まれていません。私のマシンでは、コマンドの実装とコマンドのGNU実装があります。 'realpath'が標準化されていない場合(例えば、POSIXによって)、FreeBSDとGNUの実装が完全に互換性があることはありません。運が良ければ、彼らは共通の機能のサブセットを持っています。 macOS上には 'readlink'コマンドがありますが、GNUのバージョンよりはるかに少ないオプションしかありません(' -n'オプションがあり、どちらも同じように見えます)。 –

1

バッシュのcdコマンドは面白いが、少し使用されるオプション、-P-Lのカップルを持っています。

cd [-L|[-P [-e]] [[email protected]]] [dir] 
     ... The -P option causes cd to use the physical directory 
     structure by resolving symbolic links while traversing dir and 
     before processing instances of .. in dir (see also the -P option 
     to the set builtin command); the -L option forces symbolic links 
     to be followed by resolving the link after processing instances 
     of .. in dir. ... 

だから...あなたはあなたの現在の作業ディレクトリのファイルシステム内の物理的な場所を探しているなら、あなたはこのようなものを使用できます:あなたのコメントで

realwd="$(cd -P .; pwd)" 

を、あなたがいることを言及しましたディレクトリの親ディレクトリを探しています。にはファイルが含まれています。したがって、パスが/foo/bar/baz/filenameの場合は、/foo/barを探しています。

これを得るには、cd -Pとパラメータ拡張の組み合わせをお勧めします。あなたは/文字がファイル名の一部として存在することはできません、次はあなたのために働く可能性があることを知っているので:

grandparent() { 
    local realdir="$(cd -P "${1%/*}"; pwd)" 
    echo "${realdir%/*}" 
} 

これはにパラメータ展開、その後、ファイルの物理的な場所を「取得」するcd -Pを使用して動作しますパスの最後の項目を削除します。

$ mkdir -p one/two/three 
$ touch one/two/three/foo 
$ ln -s one/two/three bar 
$ ls -l bar 
lrwxr-xr-x 1 ghoti wheel 13 Nov 19 23:05 bar -> one/two/three 
$ grandparent bar/foo 
/usr/home/ghoti/tmp6/one/two 
+0

'-L'と' -P'は[bashに固有ではありません](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cd.html)です。 – kdhp

+1

@kdhp - 本当ですが、それらも普遍的ではありません - そこにはまだtcshユーザーがいます。 OPが彼の質問にタグを付けたので、彼らはbashオプションだと言いました[tag:bash]。私の答えの関数はPOSIXシェルで動作するはずです。また、bashでも動作します。 :) – ghoti