web-dev-qa-db-ja.com

Ubuntu bashスクリプト:最後のスラッシュでパスを分割する方法は?

ファイルがあります(たとえばlist.txt)ファイルへの相対パス、1行に1つのパス、つまり次のようなものが含まれます。

foo/bar/file1
foo/bar/baz/file2
goo/file3

一度に1つのパスを処理し、最後のスラッシュで分割してから、2つのパスを引数として渡す別のプロセスを起動するbashスクリプトを作成する必要があります。これまでのところ、ループ部分のみがあります。

for p in `cat list.txt`
do
   # split $p like "foo/bar/file1" into "foo/bar/" as part1 and "file1" as part2
   inner_process.sh $part1 $part2
done

どうやって分割しますか?パスにスラッシュがない場合、これは縮退した場合に機能しますか?

THX

43
I Z

必要なのはbasenamedirnameだけです。

part1=`dirname "$p"`
part2=`basename "$p"`
97
piokuc

適切な100%bashの方法で、スペースまたは面白い記号を含むファイル名に関しては安全です(inner_process.shがそれらを正しく処理しますが、それは別の話です):

while read -r p; do
    [[ "$p" == */* ]] || p="./$p"
    inner_process.sh "${p%/*}" "${p##*/}"
done < list.txt

また、ファイルごとにdirnameおよびbasename(サブシェル内)をフォークしません。

[[ "$p" == */* ]] || p="./$p"は、$pにスラッシュが含まれていない場合に備えて、./を先頭に追加しています。

%の詳細については、 Bash Reference ManualShellパラメーター展開 セクションを参照してください。 ##シンボル。

13
gniourf_gniourf

@piokucの回答に対する@gniourf_gniourfの批判に対応し、簡潔かつシンプルに(効率的でないとしても)維持するには:

part1=`dirname "$p"`
part2=`basename "$p"`

(私はコメントで答えたでしょうが、それは構文的に不可能です。)

4
Gordon

これからの素晴らしい解決策 source

p=/foo/bar/file1
path=$( echo ${p%/*} )
file=$( echo ${p##/*/} )

これは、パス内のスペースでも機能します!

1
Phil Roggenbuck