Get just the filename from a path in a Bash script
本问题已经有最佳答案,请猛点这里访问。
如何获取不带扩展名和路径的文件名?
以下内容不提供扩展名,但我仍附加了路径:
1 | source_file_filename_no_ext=${source_file%.*} |
大多数类似于Unix的操作系统都有一个用于非常相似目的的
1 2 3 4 | pax> a=/tmp/file.txt pax> b=$(basename $a) pax> echo $b file.txt |
很遗憾,这只是给了您文件名,包括扩展名,所以您还需要找到一种方法来去掉它。
因此,考虑到无论如何都必须这样做,您还可以找到一个方法,可以去掉路径和扩展名。
实现这一点的一种方法(这是一种仅限于
1 2 3 4 5 6 7 8 9 10 | 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 |
这个小片段设置了
1 2 | FILE_PATH="/opt/datastores/sda2/test.old.img" echo"$FILE_PATH" | sed"s/.*\///" |
这将返回与
这是不带扩展名的salt文件名:
1 | echo"$FILE_PATH" | sed -r"s/.+\/(.+)\..+/\1/" |
返回
下面的语句给出了类似于
1 | echo"$FILE_PATH" | sed -r"s/(.+)\/.+/\1/" |
返回
以下是从路径获取文件名的简单方法:
1 | echo"$PATH" | rev | cut -d"/" -f1 | rev |
要删除可使用的扩展名,假定文件名只有一个点(扩展点):
1 | cut -d"." -f1 |
1 2 | $ source_file_filename_no_ext=${source_file%.*} $ echo ${source_file_filename_no_ext##*/} |
1 | $ file=${$(basename $file_path)%.*} |
因为regex(regi?)棒极了!
下面是一个简单的regex来完成这项工作:
1 | regex="[^/]*$" |
示例(GRIP):
1 2 3 4 | FP="/hello/world/my/file/path/hello_my_filename.log" echo $FP | grep -oP"$regex" #Or using standard input grep -oP"$regex" <<< $FP |
实例(AWK):
1 2 3 | 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 |
如果需要更复杂的regex:例如,您的路径被包装在一个字符串中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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:\(/[a-z]*\)\( \)\([a-z]*/\):\1\3:g') grep -oP"$regex" <<< $NewStrFP |
包含正则表达式的总解决方案:
这个函数可以为您提供Linux文件路径扩展名或不扩展名,即使文件名中有多个"."。它还可以处理文件路径中的空格,以及文件路径是否嵌入或包装在字符串中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #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" |
如果您必须处理Windows路径,可以从以下路径开始:
1 | [^\\]*$ |