在bash中获取由特定分隔符分隔的字符串的最后一个字段

时间:2014-10-28 08:47:55

标签: bash

我正在编写一个脚本,使用bash脚本将一组文件复制到目录中。我尝试复制的文件可能已存在于目录中,因此我必须重命名该文件以避免替换原始文件。

例如,如果我必须复制一个名为" abc.dd.java"的文件。并且已存在具有相同名称的文件,我必须将文件重命名为" abc.dd1.java"并复制它。

如果目的地包含" abc.dd.java"和" abc.dd1.java"然后应该重命名文件" abc.dd2.java"

我写了一段代码片段:

#$file contains the full path for the original file.
#$path contains the full path for the copied file.

copypath="$path"
echo "$path"
count=1
while [ -f "$path" ]
do
    part1=`echo "$copypath" | awk 'BEGIN{FS="."}{for(i=1;i<NF-1;i++){printf("%s.",$i)}printf("%s",$(NF-1))}END{}'`
    part2=`echo "$copypath" | awk 'BEGIN{FS="."}{printf("%s",$NF)}END{}'`
    path="$part1""$count.""$part2"
    count=`expr "$count" + 1`
done
cp "$file" "$path"

这确实有效。但它看起来太粗糙了。是不是有更好的方法来分离文件扩展名部分和名称部分?

提前致谢

3 个答案:

答案 0 :(得分:2)

要拆分文件名和扩展名,您可以使用以下字符串操作

filename="/tmp/example.txt"

# will output "txt" (extention)
echo ${filename##*.} 

# will output "/tmp/example" 
echo ${filename%%.*} 

答案 1 :(得分:1)

Extract filename and extension in bash已回答了类似的问题。

这是一个简单的版本,(大部分)基于该链接工作:

part1="${copypath%.*}"            # remove file extension (shortest .* suffix)
part2="${copypath##*.}"           # remove base path (longest *. prefix)
path="${part1}${count}.${part2}"

这是一个更完整的答案,它也处理没有扩展名的文件:

if [[ "$copypath" =~ [^/.][.][^/.]+$ ]]
then
    # copypath has an extension
    part1="${copypath%.*}"
    part2=".${copypath##*.}"
else
    # no valid extension, so insert the number at the end
    part1="$copypath"
    part2=""
fi
path="${part1}${count}${part2}"

特点:

  • 空白处理得很好。
  • 根据要求处理多个点 例如abc.dd.java变为abc.dd1.java
  • 正确处理没有扩展名的文件 例如file变为file1
  • 没有扩展名的点文件也可以正常处理 例如.bashrc变为.bashrc1

注意事项:

  • 不特别处理多个扩展程序 例如archive.tar.gz变为archive.tar1.gz而不是archive1.tar.gz
  • 如果扩展前的部分以点结尾,则不认为是扩展名 例如This is a sentence..txt成为This is a sentence..txt2
    要将此视为具有扩展名,请将正则表达式更改为[^/][.][^/.]+$
  • 不尝试处理目录。
  • 仅在Bash中测试过,不太可能与其他shell一起使用(但可以更改为使用grep)。

答案 2 :(得分:0)

尝试使用带有某些内容的.java文件:

fname=$(basename file.java .java)
echo $fname

输出:

file

然后你可以进行进一步的处理。