ファイルパスからファイル名や拡張子を自由に取り出す

いつも、いざ使う時になって、どうやるんだっけ?と探し回ってしまうので、忘れないようにメモ。(以前の日記でも、所々分散して書いているかもしれないが、ここで総括的に記録することにした)

シェルスクリプト

$ fpath='/a/b/c.d.e'

# ファイル名を取り出す(拡張子あり)
$ fname_ext="${fpath##*/}"
$ echo $fname_ext
c.d.e

# ファイル名を取り出す(拡張子なし)
$ fname="${fname_ext%.*}"
$ echo $fname
c.d

# 拡張子を取り出す
$ fext="${fpath##*.}"
$ echo $fext
e

# ディレクトリを取り出す
$ fdir="${fpath%/*}"
$ echo $fdir
/a/b

なるほど!


そして、仕組みとしては、以下のルールしたがって変換されているようだ。

${変数#パターン}	先頭から最短一致した部分を取り除く
${変数##パターン}	先頭から最長一致した部分を取り除く
${変数%パターン}	末尾から最短一致した部分を取り除く
${変数%%パターン}	末尾から最長一致した部分を取り除く


複合技としてファイルパスの拡張子だけ変更するなんてことも簡単なのだ。

$ echo "${fpath%.*}.x"
/a/b/c.d.x

また、ファイル名とディレクトリだけなら、専用コマンドも用意されてる。

$ basename '/a/b/c.d.e'
c.d.e

$ dirname '/a/b/c.d.e'
/a/b

AppleScript

  • 自分自身のファイルパスを取得


path to me
--alias "Macintosh HD:Users:zari:Library:Scripts:test_path_to.me.scpt"

  • ファイル名を取得


tell application "Finder" to (path to me)'s name
--"test_path_to.me.scpt"


tell application "Finder" to (path to me)'s folder as text
--"Macintosh HD:Users:zari:Library:Scripts:"

  • UNIX形式のパスに変換


(path to me)'s POSIX path
--"/Users/zari/Library/Scripts/test_path_to.me.scpt"


POSIX file "/Users/zari/Library/Scripts/test_path_to.me.scpt"
--file "Macintosh HD:Users:zari:Library:Scripts:test_path_to.me.scpt"

  • ファイル名と拡張子に分解するのはちょっと面倒くさい...。


tell application "Finder" to set fname_ext to (path to me)'s name
set my text item delimiters to "."
set fext to fname_ext's text items's item -1 --"scpt"
set fname to fname_ext's text items's items 1 thru -2 as text --"test_path_to.me"
set my text item delimiters to ""


もっとシンプルに書けたのであった。(感謝です!)
fnameが、fname_ext・fextに依存しないように修正。


tell application "Finder"
set select_list to selection
repeat with f in select_list
set fname_ext to f's name --ファイル名&拡張子
set fext to f's name extension --拡張子
--set fname to fname_ext's characters 1 thru -((count fext's character) + 2) as text --ファイル名
set fname to (f's name as text)'s items 1 thru -(((f's name extension as text)'s length) + 2) as text --ファイル名
set fdir to f's folder as alias --ディレクト
end repeat
end tell

fname_ext & return & fext & return & fname & return & fdir

AppleScriptからシェルスクリプトを呼び出してしまう方法


set fpath to (path to me)'s POSIX path
--"/Users/zari/Library/Scripts/test_path_to.me.scpt"

set fname_ext to do shell script "n=" & fpath's quoted form & ";echo \"${n##*/}\""
--"test_path_to.me.scpt"

set fname to do shell script "n=" & fname_ext's quoted form & ";echo \"${n%.*}\""
--"test_path_to.me"

set fext to do shell script "n=" & fpath's quoted form & ";echo \"${n##*.}\""
--"scpt"

set fdir to do shell script "n=" & fpath's quoted form & ";echo \"${n%/*}\""
--"/Users/zari/Library/Scripts/"

      • 半角¥は半角\に置き換える

Ruby

$ irb
irb(main):001:0> File::basename('/a/b/c.d.e')
=> "c.d.e"
irb(main):002:0> File::basename('/a/b/c.d.e', '.*')
=> "c.d"
irb(main):003:0> File::extname('/a/b/c.d.e')
=> ".e"
irb(main):004:0> File::dirname('/a/b/c.d.e')
=> "/a/b"

なるほど!(Rubyが最も手間最小で自然な文法だと思った)

AppleScriptからRubyを呼び出してしまう方法


set fpath to "/a/b/c.d.e"
do shell script "ruby -e \"puts File::basename(" & fpath's quoted form & ")\""
do shell script "ruby -e \"puts File::basename(" & fpath's quoted form & ", '.*')\""
do shell script "ruby -e \"puts File::extname(" & fpath's quoted form & ")\""
do shell script "ruby -e \"puts File::dirname(" & fpath's quoted form & ")\""

      • 半角¥は半角\に置き換える

AppleScriptのライブラリにしておく

シェルコマンドと組み合わせて、使い回せる関数ライブラリにしてみた。


--(*
tell application "Finder"
set select_list to selection
end tell
repeat with f in select_list
my fname_ext(f as text) my fname(f as text) my fext(f as text) my fdir(f as text) end repeat
--*)
--ファイル名&拡張子を返す
on fname_ext(f) tell application "Finder" to (f as alias)'s name
end fname_ext

--ファイル名のみ返す(拡張子なし)
on fname(f) do shell script "n=" & my fname_ext(f)'s quoted form & ";echo \"${n%.*}\""
end fname

--拡張子を返す
on fext(f) do shell script "n=" & f's POSIX path's quoted form & ";echo \"${n##*.}\""
end fext

--ディレクトリを返す
on fdir(f) tell application "Finder" to (f as alias)'s folder as text
end fdir

      • 半角¥は半角\に置き換える