从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 

basenamedirname解决scheme更方便。 这些是替代命令:

 FILE_PATH="/opt/datastores/sda2/test.old.img" echo "$FILE_PATH" | sed "s/.*\///" 

这返回test.old.imgbasename

这是没有扩展名的盐文件名:

 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)%.*}