Help with modifying a filename

Hello,

I have a filename that looks like this:

ABC_96_20141031_041133.232468

I need to shorten only the "_2014" part of the filename to simply "_14" so the filename looks like:

ABC_96_141031_041133.232468

I have to do a search for this string because there are hundreds of files and the 96 after the ABC is a sequence number, so some files are like ABC_1_20141031, ABC_10_2014 and ABC_100_2014.

I can rename files and take out or add a prefix and suffix but struggle when it comes to changing anything in the middle. :rolleyes:

How can I accomplish this please?

ls * | perl -lne 'print "$& $_" if s/(^[A-Z]{3}_\d+_)\d\d(\d\d.*$)/$1$2/'

If you like the result then change the red part to rename the files:

ls * | perl -lne 'rename $&, $_ if s/(^[A-Z]{3}_\d+_)\d\d(\d\d.*$)/$1$2/'

Try this:

ls *_*_2014*_*.* | while read original
do
 new=$(echo "$original" | awk -F_ 'BEGIN{OFS="_"}{gsub(/^20/,"",$3); print}')
 echo "$original" "$new"
done

or even this, utilizing bash's built-ins:

ls *_*_2014*_*.* | while read original
do
#disassembling sample file ABC_96_20141031_041133.232468
 piece1=${original##*_} # piece1 now holding 041133.232468
 piece2=${original%_*}  # piece2 now holding ABC_96_20141031
 piece3=${piece2%_*}    # piece3 now holding ABC_96
 piece4=${piece2##*_}   # piece4 now holding 20141031
 piece5=${piece4:2}     # piece5 now holding 141031
#reassembling
 echo "$original" "$piece3"_"$piece5"_"$piece1"
done

In both cases you'll need to substitute echo with mv to perform the actual rename process.

An another solution, with sed

ls * | while read file
do 
mv $file $(echo $file | sed 's/\(ABC_\)\([0-9]*_\)\(2014\)\(.*\)/\1\214\4/')
done

Wow! Those are some interesting ways. I accomplished it use the following:

ls -1 XV4_* | awk '{print("mv "$1 " " $1)}' | sed 's/_2014/_14/2' > rename_files.txt

Then made the rename_files.txt executable and ran it. I'm going to have to study up on some of the ways suggested, but the good thing with this site is, should I need this method again, just come look.

Thanks everyone!

That works, but this will be smaller/faster/less consumptive:

ls -1 XV4_* | awk '{X=$1; sub(/_2014/,"_14",X); print "mv", $1,X}'
or
ls -1 XV4_*| sed  's/\(.*\)/mv \1 \1/;s/_2014/_14/2' 

Did you consider to just use (recent) shell builtins

for FN in ABC_*; do echo mv "$FN" "${FN/_2014/_14}"; done

?

Try:

for f in *_*_20*_*.*
do
  [ -f "$f" ] && mv -- "$f" "${f%_*_*}_${f#*_*_20}"
done

What about

 mmv

Regards
xabbu

Rudi or anyone can you please explain what XV_4 means? I try to run this as a test and naming the file just like the question. Thanks

Do you mean XV4_*

Any file or directory name that starts with the characters X,V,4, and _, that may or may not have any other characters following after that.

Thanks, so since the filename starts with ABC....should I replace XV4_ with ABC_

That should do it

mv -rwxrw-r--. -rwxrw-r--
I keep getting that response...also I subsituted all the instances of X for A...X=$1 I used A=$1

It is hard to see but that's a dash number one, and not a dash `el'
ls -1 XV4_*

Thanks you are right, it worked with a ls -1 not l....new to this, never used ls -1 before. I need to go find out the difference

Note: ls -1 is the same as ls , when the output is not a terminal, so the -1 option is unnecessary here.

hmmm what does not a terminal mean?

Also the command I ran changed it in the response...but not permanently so when I do a ls -l I still see the old name, even though the command seemed to have changed it from the response

When we issue the command

ls

the output is to a terminal and it looks something like this:

$ ls
file1	file12	file15	file18	file20	file23	file3	file6	file9
file10	file13	file16	file19	file21	file24	file4	file7
file11	file14	file17	file2	file22	file25	file5	file8

But when we output the command to a file or a pipe for example, the output looks like this:

$ ls | cat
file1
file10
file11
file12
file13
file14
file15
file16
file17
file18
file19
file2
file20
file21
file22
file23
file24
file25
file3
file4
file5
file6
file7
file8
file9

Here ls is the same as ls -1

1 Like