Home > front end >  Rename multiple files in bash (1->11,2->12)
Rename multiple files in bash (1->11,2->12)

Time:10-22

I am trying to rename files which are in the schema A_B_x.csv, where x is in (1..10), what I want is to exactly have A_B_x 10.csv, e.g. if the file was A_B_1.csv I would like to have A_B_11.csv. I am pretty new to bash and have not found a solution, I tried:

for f in *.csv;
do 
   
    newname=`echo $f | sed 's/1.csv/11.csv/g'`;
    mv $f $newname;

done

which replaces all 1's with 11's, but I am not sure how to generalize it so it works for all numbers. Does someone has an idea?

CodePudding user response:

Would you please try the following:

for f in *.csv; do
    num=$(( ${f//[^0-9]}   10 ))
    mv "$f" "$(sed -E 's/([^0-9] )[0-9] (. )/\1'"$num"'\2/' <<< "$f")"
done
  • ${f//[^0-9]} extracts digits from the variable $f
  • num=$(( ${f//[^0-9]} 10 )) assigns num to the digits 10.
  • "$(sed -E 's/([^0-9] )[0-9] (. )/\1'"$num"'\2/' <<< "$f")" returns the file name with the number substituted by $num.

[Alternative]
If the perl rename command is available, you can also say:

rename 's/(\d )/$&   10/e' *.csv

Please note there are two different rename commands.

CodePudding user response:

You don't need sed for this (but of course you can use it). With only bash:

pre="${f%_*}"
tmp="${f##*_}"
num="${tmp%.csv}"
new="${pre}_$((num 10)).csv"

CodePudding user response:

You can do it quite simply with the bash builtin Parameter Expansions. You first trim the extension from the filename with fn="${j%.csv}". Save the base filename without the number as base="${j%_*}". Save the extension with ext="${j##*.}", and finally isolate the number with num="${fn##*_}"

Now just add 10 to the number, num=$((num 10)) and put the filename back together, new="${base}_${num}.${ext}" and then move j to new.

You can do that as:

for j in A_B*; do
    fn="${j%.csv}"       ## filename w/o extension
    base="${j%_*}"       ## base filename w/o number
    ext="${j##*.}"       ## save extension
    num="${fn##*_}"      ## isolate number

    num=$((num 10))      ## add 10 to number
    
    new="${base}_${num}.${ext}"     ## reconstitute filename w/new number
    
    echo "$j -> $new"    ## output result
    # mv "$j" "$new"     ## **Uncomment** to actually perform the move
done

Bash provides many, many useful parameter expansions, the set relevant to trimming from the front (beginning) and back (end) of a string are:

    ${var#pattern}      Strip shortest match of pattern from front of $var
    ${var##pattern}     Strip longest match of pattern from front of $var
    ${var%pattern}      Strip shortest match of pattern from back of $var
    ${var%%pattern}     Strip longest match of pattern from back of $var

(note: pattern can contain the normal globbing characters such as '*')

Example Use/Output

If you had filenames A_B_1.csv to A_B_5.csv in the current directory, the result would be:

A_B_11.csv
A_B_12.csv
A_B_13.csv
A_B_14.csv
A_B_15.csv
  •  Tags:  
  • bash
  • Related