LinuxやUNIXで、コンソール上でフルパスからファイル名のみを抽出する場合、以下のような方法がある。

1. basenameコマンドを用いる

基本はこれ。 basenameという、ファイル名のみ(ディレクトリを指定したら最後)を求めるコマンドがあるので、これを利用する。

パイプで渡す場合はxargsを使う必要があるので注意。

bash
basename PATH
shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* /opt/td-agent/LICENSE /opt/td-agent/LICENSES /opt/td-agent/bin /opt/td-agent/embedded /opt/td-agent/etc /opt/td-agent/usr /opt/td-agent/version-manifest.json /opt/td-agent/version-manifest.txt [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* | xargs -n1 basename LICENSE LICENSES bin embedded etc usr version-manifest.json version-manifest.txt

なお、basenameコマンドの場合スペースを含んだPATHを渡す場合はエスケープなり、ダブルクォーテーションなりでくくってやる必要があるので注意。

shell
[root@BS-PUB-CENT7-02 ~]# basename /opt/td-agent/space test space [root@BS-PUB-CENT7-02 ~]# basename /opt/td-agent/space\ test space test [root@BS-PUB-CENT7-02 ~]# basename "/opt/td-agent/space test" space test

xargsで渡す場合は、-Iと組み合わせてやるといいだろう。

shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/space* /opt/td-agent/space test [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/space* | xargs basename space [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/space* | xargs -I{} basename "{}" space test

一応、拡張子(.txtなど)を指定することで、その拡張子を排除して出力させることもできる…のだが、ベタ打ちなのであまり使い勝手はよくないかも。

shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* /opt/td-agent/LICENSE /opt/td-agent/LICENSES /opt/td-agent/bin /opt/td-agent/embedded /opt/td-agent/etc /opt/td-agent/space test /opt/td-agent/usr /opt/td-agent/version-manifest<span style="color: #0000ff;">.json</span> /opt/td-agent/version-manifest<span style="color: #ff0000;">.txt</span> [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* | xargs -I{} basename {} .txt LICENSE LICENSES bin embedded etc space test usr version-manifest<span style="color: #0000ff;">.json</span> version-manifest

2. awkを用いる

awkでディレクトリ部分を除外する場合は、区切り文字を「/」にしてやり、$NF(最後の列)をprintしてやればよい。

bash
awk -F/ '{print $NF}'
shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* /opt/td-agent/LICENSE /opt/td-agent/LICENSES /opt/td-agent/bin /opt/td-agent/embedded /opt/td-agent/etc /opt/td-agent/space test /opt/td-agent/usr /opt/td-agent/version-manifest.json /opt/td-agent/version-manifest.txt [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* | awk -F/ '{print $NF}' LICENSE LICENSES bin embedded etc space test usr version-manifest.json version-manifest.txt

拡張子も除外する場合は、awk内でgsubを使って置換してやるといいだろう。 記述例は以下。

bash
awk -F/ '{gsub (/\.[^/.]*$/,"",$NF);print $NF}'
shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* /opt/td-agent/LICENSE /opt/td-agent/LICENSES /opt/td-agent/bin /opt/td-agent/embedded /opt/td-agent/etc /opt/td-agent/space test /opt/td-agent/usr /opt/td-agent/version-manifest.json /opt/td-agent/version-manifest.txt [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/* | awk -F/ '{gsub (/\.[^/.]*$/,"",$NF);print $NF}' LICENSE LICENSES bin embedded etc space test usr version-manifest version-manifest

3. sedを用いる

awkと同様の処理を、sedを用いるパターン。 後方参照をすることで実現する。

bash
sed -E 's/^(\/.*\/)*(.*)/\2/' sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2/' # 拡張子もけずるパターン
shell
[root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/*.* /opt/td-agent/version-manifest.json /opt/td-agent/version-manifest.txt [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/*.* | sed -E 's/^(\/.*\/)*(.*)/\2/' version-manifest.json version-manifest.txt [root@BS-PUB-CENT7-02 ~]# ls -1ad /opt/td-agent/*.* | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2/' version-manifest version-manifest

4. bashのパラメータ展開を用いる

一度変数に代入する必要はあるが、bashのパラメータ展開を用いる方法もある。

bash
${VAR##*/}
shell
[root@BS-PUB-CENT7-02 ~]# TEST_PATH=/opt/td-agent/version-manifest.json [root@BS-PUB-CENT7-02 ~]# echo $TEST_PATH /opt/td-agent/version-manifest.json [root@BS-PUB-CENT7-02 ~]# echo ${TEST_PATH##*/} version-manifest.json

拡張子の削除は同時に行えないので、awkやsedと組み合わせるとよいだろう。

番外編 ~出力元がfindの場合~

そもそも、変換元のPATHの出力をfindで行っているのであれば、「-printf」でファイル名だけを指定すればよい。

bash
find ./ -printf "%f\n"

拡張子削除については、awkやsedを用いるとよいだろう。