仅从 Bash 脚本中的路径获取文件名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3362920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:31:55  来源:igfitidea点击:

Get just the filename from a path in a Bash script

bashscriptingshell

提问by Keith

How would I get just the filename without the extension and no path?

我如何只获得没有扩展名和路径的文件名?

The following gives me no extension, but I still have the path attached:

以下没有给我任何扩展名,但我仍然附加了路径:

source_file_filename_no_ext=${source_file%.*}

回答by paxdiablo

Most UNIX-like operating systems have a basenameexecutable for a very similar purpose (and dirnamefor the path):

大多数类 UNIX 操作系统都有一个basename用于非常相似目的(和dirname路径)的可执行文件:

pax> a=/tmp/file.txt
pax> b=$(basename $a)
pax> echo $b
file.txt

That unfortunately just gives you the file name, includingthe extension, so you'd need to find a way to strip that off as well.

不幸的是,这只是为您提供了文件名,包括扩展名,因此您还需要找到一种方法来去除它。

So, given you have to do that anyway, you may as well find a method that can strip off the path andthe extension.

因此,鉴于无论如何您都必须这样做,您不妨找到一种可以剥离路径扩展名的方法。

One way to do that (and this is a bash-only solution, needing no other executables):

一种方法(这是一个bash唯一的解决方案,不需要其他可执行文件):

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

That little snippet sets xpath(the file path), xpref(the file prefix, what you were specifically asking for) and xfext(the file extension).

那个小片段集xpath(文件路径),xpref(文件前缀,你特别要求的)和xfext(文件扩展名)。

回答by F?rat Kü?üK

basenameand dirnamesolutions are more convenient. Those are alternative commands:

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

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

This returns test.old.imglike basename.

这返回test.old.imgbasename.

This is salt filename without extension:

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

echo "$FILE_PATH" | sed -r "s/.+\/(.+)\..+//"

It returns test.old.

它返回test.old

And following statement gives the full path like dirnamecommand.

下面的语句给出了像dirname命令一样的完整路径。

echo "$FILE_PATH" | sed -r "s/(.+)\/.+//"

It returns /opt/datastores/sda2

它返回 /opt/datastores/sda2

回答by Ivry345

Here is an easy way to get the file name from a path:

这是从路径中获取文件名的简单方法:

echo "$PATH" | rev | cut -d"/" -f1 | rev

To remove the extension you can use, assuming the file name has only ONE dot (the extension dot):

要删除您可以使用的扩展名,假设文件名只有一个点(扩展名点):

cut -d"." -f1

回答by mihai

$ file=${$(basename $file_path)%.*}

回答by ghostdog74

$ source_file_filename_no_ext=${source_file%.*}
$ echo ${source_file_filename_no_ext##*/}

回答by jkdba

Some more alternative options because regexes (regi ?) are awesome!

还有一些替代选项,因为正则表达式 (regi ?) 很棒!

Here is a Simple regex to do the job:

这是一个简单的正则表达式来完成这项工作:

 regex="[^/]*$"

Example (grep):

示例(grep):

 FP="/hello/world/my/file/path/hello_my_filename.log"
 echo $FP | grep -oP "$regex"
 #Or using standard input
 grep -oP "$regex" <<< $FP

Example (awk):

示例(awk):

 echo $FP | awk '{match(, "$regex",a)}END{print a[0]}
 #Or using stardard input
 awk '{match(, "$regex",a)}END{print a[0]} <<< $FP

If you need a more complicated regex:For example your path is wrapped in a 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:\(/[a-z]*\)\( \)\([a-z]*/\)::g')
 grep -oP "$regex" <<< $NewStrFP

Total solution with Regexes:

正则表达式的完整解决方案:

This function can give you the filename with or without extension of a linux filepath even if the filename has multiple "."s in it. It can also handle spaces in the filepath and if the file path is embedded or wrapped in a string.

即使文件名中有多个“.”,此函数也可以为您提供带有或不带有 linux 文件路径扩展名的文件名。它还可以处理文件路径中的空格以及文件路径是否嵌入或包装在字符串中。

#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=""
    local NoExtension=""
    local FileString=$(echo $FileString | sed 's:\(/[a-zA-Z0-9\<\>\|\\:\)\(\&\;\,\?\*]*\)\( \)\([a-zA-Z0-9\<\>\|\\:\)\(\&\;\,\?\*]*/\)::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"

If you have to mess with a windows path you can start with this one:

如果你不得不弄乱 Windows 路径,你可以从这个开始:

 [^\]*$