从Bash脚本的path获取文件名
我怎样才能得到没有扩展名和path的文件名?
以下给我没有延伸,但我仍然有附加的path:
source_file_filename_no_ext=${source_file%.*}
大部分类UNIX操作系统都有一个basename
可执行文件,用于非常类似的目的(和path的dirname
):
pax> a=/tmp/file.txt pax> b=$(basename $a) pax> echo $b file.txt
不幸的是,只是给你的文件名, 包括扩展名,所以你需要find一种方法来剥离。
所以,既然你必须这样做,你也可以find一种方法,可以剥离的path和扩展。
一种方法来做到这一点(这是一个纯粹的解决scheme,不需要其他可执行文件):
pax> a=/tmp/xx/file.tar.gz pax> xpath=${a%/*} pax> xbase=${a##*/} pax> xfext=${xbase##*.} pax> xpref=${xbase%.*} pax> echo;echo path=${xpath};echo pref=${xpref};echo ext=${xfext} path=/tmp/xx pref=file.tar ext=gz
这个小片段设置了xpath
(文件path), xpref
(文件前缀,你特别要求的)和xfext
(文件扩展名)。
这是从path获取文件名的简单方法:
echo "$PATH" | rev | cut -d"/" -f1 | rev
要删除可以使用的扩展名,假定文件名只有一个点(扩展点):
cut -d"." -f1
basename
和dirname
解决scheme更方便。 这些是替代命令:
FILE_PATH="/opt/datastores/sda2/test.old.img" echo "$FILE_PATH" | sed "s/.*\///"
这返回test.old.img
像basename
。
这是没有扩展名的盐文件名:
echo "$FILE_PATH" | sed -r "s/.+\/(.+)\..+/\1/"
它返回test.old
。
下面的语句给出了像dirname
命令一样的完整path。
echo "$FILE_PATH" | sed -r "s/(.+)\/.+/\1/"
它返回/opt/datastores/sda2
$ source_file_filename_no_ext=${source_file%.*} $ echo ${source_file_filename_no_ext##*/}
一些更多的替代选项,因为正则expression式(regi?)真棒!
这是一个简单的正则expression式来完成这项工作:
regex="[^/]*$"
示例(grep):
FP="/hello/world/my/file/path/hello_my_filename.log" echo $FP | grep -oP "$regex" #Or using standard input grep -oP "$regex" <<< $FP
示例(awk):
echo $FP | awk '{match($1, "$regex",a)}END{print a[0]} #Or using stardard input awk '{match($1, "$regex",a)}END{print a[0]} <<< $FP
如果你需要一个更复杂的正则expression式:例如你的path被包装在一个string中。
StrFP="my string is awesome file: /hello/world/my/file/path/hello_my_filename.log sweet path bro." #this regex matches a string not containing / and ends with a period #then at least one word character #so its useful if you have an extension regex="[^/]*\.\w{1,}" #usage grep -oP "$regex" <<< $StrFP #alternatively you can get a little more complicated and use lookarounds #this regex matches a part of a string that starts with / that does not contain a / ##then uses the lazy operator ? to match any character at any amount (as little as possible hence the lazy) ##that is followed by a space ##this allows use to match just a file name in a string with a file path if it has an exntension or not ##also if the path doesnt have file it will match the last directory in the file path ##however this will break if the file path has a space in it. regex="(?<=/)[^/]*?(?=\s)" #to fix the above problem you can use sed to remove spaces from the file path only ## as a side note unfortunately sed has limited regex capibility and it must be written out in long hand. NewStrFP=$(echo $StrFP | sed 's:\(/[az]*\)\( \)\([az]*/\):\1\3:g') grep -oP "$regex" <<< $NewStrFP
正则expression式的整体解决scheme:
即使文件名中有多个“。”,这个函数也可以给你带有或不带有扩展名的文件path的文件名。 它也可以处理文件path中的空格,以及文件path是embedded还是包装在string中。
#you may notice that the sed replace has gotten really crazy looking #I just added all of the allowed characters in a linux file path function Get-FileName(){ local FileString="$1" local NoExtension="$2" local FileString=$(echo $FileString | sed 's:\(/[a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*\)\( \)\([a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*/\):\1\3:g') local regex="(?<=/)[^/]*?(?=\s)" local FileName=$(echo $FileString | grep -oP "$regex") if [[ "$NoExtension" != "" ]]; then sed 's:\.[^\.]*$::g' <<< $FileName else echo "$FileName" fi } ## call the function with extension Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." ##call function without extension Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." "1"
如果你必须弄糟一个Windowspath,你可以从这个开始:
[^\\]*$
$ file=${$(basename $file_path)%.*}