usage: basename string [suffix]
言わずと知れたパスの最後の部分を切り取る
basename
ですが、簡単なコマンド過ぎてコマンドさえ知ったら
ヘルプも見ることもまず無いかと。
MacでおもむろにBSD版basename
を引数無しで実行してみると
$ basename
usage: basename string [suffix]
basename [-a] [-s suffix] string [...]
な感じ。 そもそもヘルプな引数すら無い模様。
LinuxなどでGNU版だと引数なしだとmissing operand
が出ますが、
--help
で見れます。
$ basename --help
Usage: basename NAME [SUFFIX]
or: basename OPTION
Print NAME with any leading directory components removed.
If specified, also remove a trailing SUFFIX.
--help display this help and exit
--version output version information and exit
Examples:
basename /usr/bin/sort Output "sort".
basename include/stdio.h .h Output "stdio".
Report basename bugs to [email protected]
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'basename invocation'
こちらは親切にExamplesまで載せてくれてます。
SUFFIXの削除
まあGNU版のヘルプを見ると一目瞭然なんですが、 2つ目の引数に拡張子などを渡してあげれば その分を後ろ側から除いてファイルの名前だけを出力する様な事が簡単に出来るわけですね。
ちなみに後ろから見て該当の文字列がなければエラーが出るわけではなく何もしません。
$ basename /aaa/bbb/ccc.cxx .cxx
ccc
$ basename /aaa/bbb/ddd.h .cxx
ddd.h
複数の文字列を同時に操作
GNU版の方は基本的に1つの引数を取ってそれのベースネームを取るだけです。 後はSUFFIXを削除する事が出来るだけ。
一方BSD版の方は複数の文字列を一度に変換することが出来ます。
この際、デフォルトでは2つの引数を与えるとGNU版同様2つ目をSUFFIXと捉えて
1つ目の引数から消そうとしてしまいますが、
オプション-a
を与える事でそれぞれの引数に別途basename
をかけることが出来ます。
$ basename /aaa/bbb/ccc /ddd/eee/fff
ccc
これだと1つ目の引数のbasename
のみ返る。
/ddd/eee/fff
はSUFFIXとみなされ、この場合はccc
からは消せないので何もしない。
一方、以下のものだと
$ basename -a /aaa/bbb/ccc /ddd/eee/fff
ccc
fff
/aaa/bbb/ccc
、/ddd/eee/fff
の両方にbasename
をかけた結果が返る。
3つ以上渡すと-a
を与えても与えなくても全てを独立の文字列とみなす様です。
$ basename /aaa/bbb/ccc /ddd/eee/fff /ggg/hhh/iii
ccc
fff
iii
$ basename -a /aaa/bbb/ccc /ddd/eee/fff /ggg/hhh/iii
ccc
fff
iii
こういった複数の文字列を一気に扱いたい時に、さらにSUFFIXを差っ引きたい場合は-s
を使います。
$ basename -a -s .h /aaa/bbb/ccc.cxx /ddd/eee/fff.h /ggg/hhh/iii.h
ccc.cxx
fff
iii
-s
を渡すと、-s <suffix>
以外の引数が2つの場合にも
-a
を使わずとも両方共文字列として扱われbasename
が2つにかけられます。
GNUで3つ以上渡すと、
$ basename /aaa/bbb/ccc /ddd/eee/fff /ggg/hhh/iii
basename: extra operand `/ggg/hhh/iii'
Try `basename --help' for more information.
な感じでエラーになります。
2つならエラーにはなりませんが、
-a
を渡せばエラーになりますし、
2つの文字列を渡すだけだと後ろ側はSUFFIXとして評価されるだけです。
BSD版の方が便利ですね。
man
を見るとBSD版がApril 18, 1994
、GNU版がGNU coreutils 8.4 March 2017
と書いてあったりするのですが、GNU版はBSD版の機能を追随しないのでしょうか?
(GNUの方はcoreutilsの全体のアップデートに従って日付がアップデートされてて
basename
自体は手を付けられてない状態なんだとは思いますが。)
この複数渡すものも知りませんでしたが、 GNUとの互換性が無いのでこれは知らなくてもそれ程問題ないかな、とも。
ちなみにdirname
ちなみに逆にパスの最後の部分だけ落としてディレクトリを返す
dirname
コマンドですが、
これはGNU/BSDどちらの場合も1つの引数を取るだけみたいです
2つ以上渡そうとすれば
$ dirname aaa bbb # BSD
usage: dirname path
$ dirname aaa bbb # GNU
dirname: extra operand `bbb'
Try `dirname --help' for more information.
と、共にエラーが出ます
またdirname
には基本的にオプション引数はありません。
GNUの方に--help
と--version
があるだけです。
また、BSD版の方はbasename
と同一パッケージになっていて
man basename
もman dirname
も同じものが表示され、
2つのコマンドについて書かれたマニュアルが表示されます。
まとめ
こんな簡単で良く使うコマンドでも知らない事がまだあるとは 自分が残念です。
まあ簡単過ぎて調べもしないのと、
拡張子除くのもcut
でもawk
でもなんでも簡単に出来るので考えもしないのと。
でも知ってたら断然便利ですね。。。
多分今まで作ったスクリプトの中でも 結構な量の無駄があると思います。
これって一体どれだけの人が知ってるんでしょうか? (意外と知らないんだと思いたいのですが
ま、多分他にも色々あるんでしょう。