如何使用sed仅获取文件名


17

如何使用sed仅获取文件名?我有这个

out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")

但是我也有道路/root/video.mp4,我只想video.mp4

Answers:


26

basename从GNU coreutils可以帮助您完成这项工作:

$ basename /root/video.mp4
video.mp4

如果您已经知道文件的扩展名,则可以basename使用以下语法调用basename NAME [SUFFIX]以将其删除:

$ basename /root/video.mp4 .mp4
video

或者另一个选择是使用以下命令剪切最后一个点之后的所有内容sed

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old

3
使用sed 's/\.[^.]*$//'你有,将失败(隐藏).filename...目录
Peter.O

9

最简单的解决方案是删除所有内容,直到最后一次出现/

echo /root/video.mp4 | sed 's/.*\///'


5

使用以下任何一种方式:

out_file="${in_file##*/}"

out_file="$(basename $in_file)"

out_file="$(echo $in_file | sed 's=.*/==')"

out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"

ps。之所以得到相同的字符串,是因为在语句\(.*\.\)中,它从开始到点(/root/video.)都与该字符串匹配,然后手动添加.mp4与原始字符串相同的字符串。您应该s=.*\([^/]*\)=\1=改用。

更新:(第一个已修复)

要获取唯一不带扩展名的文件名,您可以:

out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"

out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"

out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'

但是,使用这些方法中的任何一种,我都可以使用格式获取文件名,而我只需要获取文件名并手动放置新格式。
Shixons 2012年

嗯,那很有道理。我已经更新了答案。
着急

@rush:会有一些极端情况,例如,名为的文件my.file.tar.gz
donothing成功地

@donothing成功地在最后一个sed和缺少一个点符号awk。固定。谢谢。

4

使用正则表达式的基本原理之一是,在指定通配符时,模式本质上是贪婪的。虽然@uloBasEI提出的答案肯定是一个可行的答案,但它也需要使用basename命令。@Shixons的原始问题要求仅使用sed的解决方案。

在继续之前,了解目标版本的sed总是有帮助的。我假设BSD(与OSX一起提供)。

首先,原始问题中提出的模式不起作用,因为它会捕获从输入字符串的开始到最后一个点(包括最后一个点)的所有内容。没有锚点,此搜索将吞噬所有从左到右的内容。因此,“ / 1”匹配模式是直到最后一个点(包括最后一个点)的所有内容。即使是带有多个点的文件名也会被整个吞没。根本达不到预期的结果。

第一步是建立识别模式的策略。在这里,您想摆脱文件名左侧的所有内容(稍后我们将处理扩展名):

out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"

搜索从字符串的开头开始匹配。它与“ /.*”模式匹配零次或更多次,然后删除所有内容。我们用“ \ 1”打印匹配的模式。我们不在全球范围内搜索;我们通过指定^锚从字符串的开头进行搜索。

通过启用“ -E”选项,我们可以获得更好的清晰度,因此我们不必转义括号:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"

因此,现在我们在左侧。让我们在右侧添加零件。请注意,我们需要将左侧部分保留为模式,因为这是我们可以指定左侧部分出现零次或多次的方式。我们现在要做的就是在右侧的部分添加一个模式:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"

我们仅打印出第二个匹配项,从而丢弃文件名以外的所有内容。但是我们仍然需要删除文件扩展名。

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"

最后的“ $”是可选的。

最后,要添加新的扩展名,您需要像这样修改:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"

另一个优化是使第一个正斜杠成为可选选项以处理相对路径:

out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"

我在寻找sed模式来替换basename时很懒,从而遇到了这个问题。我正在未安装该命令的剥离系统上工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.