Home > Back-end >  renaming file name in unix
renaming file name in unix

Time:01-05

We need to rename the file from filename.dat.dat.dat to filename.dat. We have plenty of files having somewhat same type of name having extension .dat.dat.dat

using the below script:

cd /home/riya
for file in filename.dat.dat.dat
do
echo $file
new = "${file:0:12}"
echo $new
mv $file $new
done

giving below error:

riya.ksh[5]: "${file:0:12}": bad substitution

CodePudding user response:

Unless these filenames all consist of exactly eight characters followed by .dat repeated three times, you would probably be better off using regular expressions to modify them. A utility like sed can do this without any trouble.

Your question is a little unclear as to where these .dat files are located, but if they're all in the same directory then this ought to work:

for f in *.dat.dat.dat
  do
    g=$(echo $f | sed s/\\.dat\\.dat//)
    echo "$f -> $g" ; mv $f $g
  done

CodePudding user response:

@r3mainer: your solution is possible but its feasibility depends on how many such files there are: using sed (or any other external program for that matter - awk, tr, ...) will need to spawn a complete new sub-process and its environment which is quite taxing on the system. Fortunately the functionality of your sed-script can be achieved within the shell by using "parameter substitution".

@riva: first off, you code can't work because variable assignments are not allowed to have blanks in them:

 new = "${file:0:12}"    # wrong!
 new="${file:0:12}"      # correct!

Even the second one will work only depending on which shell exactly you are using. ksh88 for instance (the default shell in AIX) will not, ksh93 (the only ksh version in Linux and named "enhanced Korn shell" in AIX) will understand that.

Still, @r3mainer's critizism holds: this works only if all the filenames are guaranteed to be 8 characters long. Instead you can use parameter substitution to get what you want:

 new="filename.dat.dat.dat"
 echo ${new%%.dat*}          # this will yield "filename"
 new="${new%%.dat*}.dat"     # this will yield "filename.dat"

The expansion ${variable%%pattern} cuts pattern (in its longest possible form, "greedy match") from the end of the contents of variable. Since the pattern is ".dat*", this means everything starting with the first (of arbitrarily many) ".dat" sequences is cut. Then a single ".dat" is added at the end.

Additionally, notice that you shouldn't use "for-loops" for this kind of activity. "find" is the command for this sort of purpose:

 find /some/directory -type f -name "*.dat" -print |\
 while read FILE ; do
      mv "${FILE}" "${FILE%%.dat*}.dat"
 done
  •  Tags:  
  • Related