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?
Aia
November 1, 2014, 7:47pm
2
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!
RudiC
November 2, 2014, 12:27pm
6
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
BigT
November 4, 2014, 11:59am
9
rudic:
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
?
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
Aia
November 4, 2014, 12:04pm
10
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.
BigT
November 4, 2014, 12:07pm
11
aia:
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_
BigT
November 4, 2014, 12:49pm
13
aia:
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
Aia
November 4, 2014, 1:02pm
14
It is hard to see but that's a dash number one, and not a dash `el'
ls -1 XV4_*
BigT
November 4, 2014, 1:07pm
15
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.
BigT
November 4, 2014, 1:26pm
17
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