アメリエフのブログ

Amelieff Staff Blog

ファイルの絶対パスを取得する

こんにちはkubo改めkubo-mです。地図アプリがないと目的地にたどり着けない方向音痴です。
家族にある場所への道順を「北に向かって進んでから〇〇で東に折れて……」と説明されて、「歩いている最中に方角なんてわからないから、右に曲がるか、左に曲がるかで教えて」と訴えたところ、家族には「相対的に地図を見る派なんだね」と評されました。そんな派閥聞いたことない。

Linuxでも、ファイルやディレクトリの場所を示すのに、絶対パス相対パスの2種類の示し方があります。

絶対パスは、ディレクトリ構造の一番上(/)からファイルやディレクトリの場所を示す方法です。コマンド実行時にどんなディレクトリにいても、特定のファイルやディレクトリを指す絶対パスは同じになります。
相対パスは、コマンド実行時の位置から見て、ファイルやディレクトリの場所を示す方法です。 「ひとつ上のディレクトリにあるファイルpiyo」 「今いるディレクトリにあるファイルhoge」 「今いるディレクトリにあるhogeディレクトリの中のfoo」 という示し方なので、同じファイルについて指し示すときも、ディレクトリを移動すると相対パスは変わります。

あるファイルを処理するためにツールを実行するとき、多くの場合は絶対パスと相対パスのどちらも指定できますが、ほとんどの場合、絶対パスを指定したほうが無難です。

# 相対パス
$ samtools view -b hoge.sam -o hoge.bam
# 絶対パス
$ samtools view -b /home/user/analysis/hoge.sam -o /home/user/analysis/hoge.bam

ところで、ファイルやディレクトリの絶対パスって、みなさまどうやって取得しているのでしょうか。 実は私は、上記の例だと、/home/user/analysis/で作業していて、hoge.samの絶対パスを取得したいときは

  1. pwdで作業ディレクトリの絶対パスを取得(/home/user/analysis/
  2. ファイル名を取得(hoge.sam
  3. 作業ディレクトリのパスをファイル名を、コピー&ペーストしてから/で繋ぐ。(/home/user/analysis + / + hoge.sam/home/user/analysis/hoge.sam

という手順で取得していました。
結構手数が多いのです。
……書きだしてみたらそうでもなく見えてきました(いえいえ、このコピー&ペーストが結構手間なのです)。

毎日やっていることなので、できれば1コマンドで済ませたい。
できるはずだ!
ということで調べて2つ方法を見つけました。

readlinkコマンド

$ readlink -f hoge.sam

readlinkコマンドは、シンボリックリンクに対してオプションを付けずに実行すると、リンクの実体の絶対パスを返すコマンドです。 -fを指定すると、ファイルの絶対パスが得られました。

findコマンド

$ find `pwd` -name "hoge.sam"
/home/user/anaysis/hoge.sam

findに与える検索場所に、まさかpwdコマンドを与えられるとは、知りませんでした。
ちなみに、findはディレクトリの中を再帰的に検索するので、作業ディレクトリの中のディレクトリに同名のファイルがあると、そのファイルも出てきてしまいます。

$ find `pwd` -name "hoge.sam"
/home/user/anaysis/hoge.sam
/home/user/anaysis/test/hoge.sam

これを防ぐためには、findが検索するディレクトリの深さを指定します。

$ find `pwd` -mindepth -maxdepth 1 -name "hoge.sam"
/home/user/anaysis/hoge.sam

使い分け

readlink -fのほうが、圧倒的に短く簡便そうなので、もうreadlinkだけでいいように思えたので、最初はこの記事もreadlinkだけで終わらせる予定でした。
しかし、複数のファイルの絶対パスをまとめて取得したいときに、readlinkが使いにくいことに気づきました。

$ ls *.fastq
sampleA.fastq
sampleB.fastq
sampleC.fastq
sampleD.fastq
$ readlink *.fastq
readlink: extra operand 'filname.txt'
詳しくは `readlink --help' を実行して下さい.

どうやらワイルドカードを使うと、よくわからない挙動をするようです。 一方findコマンドは、ファイル名にワイルドカードを指定すると、下記のような結果を返します。

$ find `pwd` -name "*fastq"
/home/user/anaysis/sampleA.fastq
/home/user/anaysis/sampleB.fastq
/home/user/anaysis/sampleC.fastq
/home/user/anaysis/sampleD.fastq

状況に合わせて、使いやすいほうを選択するとよさそうですね!