hello
does someone want to help me for this one ?
i want to rename file by inversing parts of filenames separated by the delimiter "--"
sometimes filenames have three strings :
aabb4ccdd eeffgg -- 5566 -- aa78bb ccd eef gghhi.ext
to
aa78bb ccd eef gghhi -- 5566 -- aabb4ccdd eeffgg.ext
aabbcc -- 55 -- aab667ccdd ee.ext
to
aab667ccdd ee -- 55 -- aabbcc.ext
556aa -- aabb -- 7788.ext
to
7788 -- aabb -- 556aa.ext
sometimes there are only two strings :
aabbccdd eef -- gghh iijjkkl.ext
to
gghh iijjkkl -- aabbccdd eef.ext
when there are two strings i think the solution is to inverse strings separated by "--"
i've got filename like these one too, i'd like to put the digits at at the end to the beginning :
aabbccdde -- ffgghh iijjkkll5566778.ext
to
5566778 aabbccdde -- ffgghh iijjkkll.ext
aab55c -- ddeeffgghh5566.ext
to
5566 aab55c -- ddeeffgghh.ext
thanks for you help !
pamu
October 21, 2012, 4:36am
2
for above two case try this...
for i in *.ext
do
file_name=$(echo "$i" | awk -F " -- " '{split($NF,a,".");s=$1;$1=a[1];$(NF)=s"."a[2]}1' OFS=" -- ")
mv $i $file_name
done
for last having numeric at the end of file..
for i in *[0-9].ext
do
file=$(echo "$i" | awk -F "" '{for(i=1;i<=NF;i++){if($i ~ /[A-z]/){s=""}else{if($i == "."){print s}else{s=s?s""$i:$i}}}}')
file_name=$(echo "$i" | awk -v RPL="$file" '{sub(RPL,"",$0);print RPL,$0}')
mv $i $file_name
done
1 Like
msabhi
October 21, 2012, 4:55am
3
1>Verify is these are the conditions you require by just printing the mv command
ls *ext | perl -F"--" -alne '{if($#F==1){
if($F[1]=~/(\d+).ext/){ $p=$1;$F[0]=~s/^/$p /g;$F[1]=~s/$p//;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
else { ($F[0],$F[1])=($F[1],$F[0]);$F[0]=~s/.ext//;$F[1]=~s/ *$/(.ext|^ *)/;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}else{ ($F[0],$F[2])=($F[2],$F[0]);$F[0]=~s/.ext//;$F[2]=~s/ *$/(.ext|^ *)/;;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}'
2>Once you are sure of what you want execute it
ls *ext | perl -F"--" -alne '{if($#F==1){
if($F[1]=~/(\d+).ext/){ $p=$1;$F[0]=~s/^/$p /g;$F[1]=~s/$p//;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
else { ($F[0],$F[1])=($F[1],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[1]=~s/ *$/.ext/;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}else{ ($F[0],$F[2])=($F[2],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[2]=~s/ *$/.ext/;;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}' | sh
1 Like
for i in *[0-9].ext
do
file=$(echo "$i" | awk -F "" '{for(i=1;i<=NF;i++){if($i ~ /[A-z]/){s=""}else{if($i == "."){print s}else{s=s?s""$i:$i}}}}')
file_name=$(echo "$i" | awk -v RPL="$file" '{sub(RPL,"",$0);print RPL,$0}')
mv $i $file_name
done
maybe your script works but my level of understandings don't allow me to tell you anything on it !
Scott
October 21, 2012, 10:42am
5
Is there any reason why all of that code is on a single line? Do you think that helps your 'level of understanding'?
For me, it's unreadable.
edit: you updated it. It's marginally more readable.
ls *ext | perl -F"--" -alne '{if($#F==1){
if($F[1]=~/(\d+).ext/){ $p=$1;$F[0]=~s/^/$p /g;$F[1]=~s/$p//;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
else { ($F[0],$F[1])=($F[1],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[1]=~s/ *$/.ext/;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}else{ ($F[0],$F[2])=($F[2],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[2]=~s/ *$/.ext/;;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}' | sh
for moving numeric to the beginning, this script works perfectly !
???
i have a question can the script is capable to rename directories
pamu
October 21, 2012, 11:10am
8
If i don't understand any script which have lot of conditions and scenarios, I prefer to test script part by part. Divide script into multiple pieces so it can be understandable.. Run script part by part....
Please read this
the directories looks like this :
aabbccdde -- ffgghh iijjkkll5566778
to
5566778 aabbccdde -- ffgghh iijjkkll
sometimes there's only one string
aab55ccddeeffgghh6677
to
6677 aab55ccddeeffgghh
thanks !
msabhi
October 21, 2012, 11:45am
10
No my script doesn't work for these directories you have mentioned since its different conditions all together....But you can use the logic in my script as a workaround ..let me know if any help required in the same..
1 Like
Try shell only:
for file in *.ext
do
first=${file%% -- *}
secondext=${file##* -- }
second=${secondext%.*}
ext=${file##*.}
middle=${file#$first}
middle=${middle%$secondext}
mv "$file" "$second$middle$first.$ext"
done
1 Like
that's what i want to ask you after the precision, do you want to help to understand a little bit of your script
what are the meaning of
$p
$1
$F[0]
$F[1]
mc2z674gj:
the directories looks like this :
aabbccdde -- ffgghh iijjkkll5566778
to
5566778 aabbccdde -- ffgghh iijjkkll
sometimes there's only one string
aab55ccddeeffgghh6677
to
6677 aab55ccddeeffgghh
thanks !
Your requirement seems to have changed. There is no separator in the second example ?
And the first example does not switch left and right side...
1 Like
for inversing strings delimited by "--" in filenames, this script works perfectly !
that put the last string to the beginning & vice versa
---------- Post updated at 07:12 PM ---------- Previous update was at 06:15 PM ----------
thanks for your perspicacity ! you're right i've found a solution when there are only one string
i add " -- " at the end to fits the script
so don't take that example (aab55ccddeeffgghh6677)
i only need want to know if the script works for the directories
i've checked the mv command page and adding "-t" option perhaps may help
but i don't quite sure and i don't know if it fit in the script
ls *ext | perl -F"--" -alne '{if($#F==1){
if($F[1]=~/(\d+).ext/){ $p=$1;$F[0]=~s/^/$p /g;$F[1]=~s/$p//;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
else { ($F[0],$F[1])=($F[1],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[1]=~s/ *$/.ext/;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}else{ ($F[0],$F[2])=($F[2],$F[0]);$F[0]=~s/(.ext|^ *)//;$F[2]=~s/ *$/.ext/;;print "mv \"$_\" \"".join(" -- ",@F)."\"" ;}
}' | sh
msabhi
October 21, 2012, 1:23pm
15
Ok.
1>First store all the necessary directory names into one file like "temp" and execute as usual to check if this is satisfying your conditions
perl -lne '{$Tget=$_;$_=~s/(.*?)(\d+)$/$2 $1/g;print "mv \"$Tget\" \"$_\""}' temp
mv "aabbccdde -- ffgghh iijjkkll5566778" "5566778 aabbccdde -- ffgghh iijjkkll"
mv "aab55ccddeeffgghh6677" "6677 aab55ccddeeffgghh"
2>Execute the same now
perl -lne '{$Tget=$_;$_=~s/(.*?)(\d+)$/$2 $1/g;print "mv \"$Tget\" \"$_\""}' temp | sh
---------- Post updated at 01:23 PM ---------- Previous update was at 01:14 PM ----------
And one more thing...
normal mv works for directories also...you don't have to use any option unless some peculiar case which i may not have come across...
-t option is invalid usage here. This is what man page says :
-t, --target-directory=DIRECTORY
move all SOURCE arguments into DIRECTORY
which means moving(not renaming) multiple files into a directory.
1 Like
Hi msabhi, perl does have a file rename operator, if you'd forgotten about it.
1 Like
msabhi
October 21, 2012, 1:31pm
17
Right elixir...new to PERL workarounds for files..somehow forgot its usage:wall:
Below code would be more efficient...
perl -lne '{$Tget=$_;$_=~s/(.*?)(\d+)$/$2 $1/g;rename "$Tget", "$_"}' temp
1 Like
thanks for your helpings to all, i really appreciate it !