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

1. basenameコマンドを用いる

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

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

basename PATH
[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を渡す場合はエスケープなり、ダブルクォーテーションなりでくくってやる必要があるので注意。

[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と組み合わせてやるといいだろう。

[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など)を指定することで、その拡張子を排除して出力させることもできる…のだが、ベタ打ちなのであまり使い勝手はよくないかも。

[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してやればよい。

awk -F/ '{print $NF}'
[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を使って置換してやるといいだろう。 記述例は以下。

awk -F/ '{gsub (/\.[^/.]*$/,"",$NF);print $NF}'
[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を用いるパターン。 後方参照をすることで実現する。

sed -E 's/^(\/.*\/)*(.*)/\2/' 
sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2/' # 拡張子もけずるパターン
[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のパラメータ展開を用いる方法もある。

${VAR##*/}
[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」でファイル名だけを指定すればよい。

find ./ -printf "%f\n"

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