0

I have got strings like tran_crossings_exp_.txt and tran_buildings_exp_.shp How can I write a bash function to test if the last character before the dot extension starts with an underscore and replace the underscore to have a name like tran_crossings_exp.txt I know how to get the basename and extension of the file in bash

I have done this solution but I am seeking a more elegant way which also check if the file indeed has an underscore and skips it if the name already is proper.

for file in `ls *_.*`;do ext="${file##*.}"; filename="${file%.*}";non=${file::-5}; mv ${file} ${non}.${ext};done
alseether
  • 1,889
  • 2
  • 24
  • 39
kartoza-geek
  • 341
  • 1
  • 6
  • 20

2 Answers2

0

Try with this:

#!/bin/bash

filename=tran_crossings_exp_.txt
i=${filename:${#filename}-5:1}  // Take the 5th char from back
if [ $i = "_" ]; then           // If it is an underscore
    echo "${filename/?./.}"     // Replace '?.' with just '.', this removes last '_' in this case (? means any character)
else
    echo $filename
fi

Here you can test it

Note: this only works with .abc (dot and 3 chars) extensions

EDIT

To store in the same variable

#!/bin/bash

filename=tran_crossings_exp_.txt
i=${filename:${#filename}-5:1}

if [ $i = "_" ]; then
    filename="$(echo ${filename/?./.})"
fi

echo "$filename"
alseether
  • 1,889
  • 2
  • 24
  • 39
0

This works if the file has only one dot (.) and any extension.

It uses string substitution.

One liner to see result of removing underscore:

find . -name "*_.*" | while IFS= read -r file; do echo "${file//_./.}"; done

Explanation: first find only those files which have an underscore followed by dot and then some extension. Then use string substitution to change _. to only .

To Rename:

find . -name "*_.*" | while IFS= read -r file;
do
mv "$file" "${file//_./.}"
done
Rajib
  • 453
  • 7
  • 10