0

I mention that I've already checked similar questions about renaming files with bash script, but none has helped me with this problem.

I need to rename many files in a directory after the following rule: list the current files alphabetically, then replace their name with a given basic name, add a suffix which is the current file index and then add a given extension.

I encountered a problem at indexing the files. For instance, if I had 1000 files, after executing the script their names should be file0001.ext, file0002.ext ... file0010.ext ... file0099.ext ... file 0100.ext ... file0999.ext, file1000.ext.

I've computed the needed number of zeros for every file, but I do not know how to implement the rule with a regular expression within the mv commnad. Below is my script code:

#!/bin/bash

nod=0

i=1
nof=$(ls -v $3 | wc -l)
cpy=$nof
while [ $cpy -gt 0]
do
    nod=$((nod+1))
    cpy=$((cpy/10))
done
for a in $(ls -v $3)
do
    cpy_of_i=$i
    i_digits=0
    while [ $cpy_of_i -gt 0 ]
    do
        i_digits=$((i_digits+1))
        cpy_of_i=$((cpy_of_i/10))
    done
    nr_zeros=$((nod-i_digits))
    old=$3$a
    new=$(echo $3$1[0]\*{nr_zeros}$i.$2)
    mv $old $new
    i=$((i+1))
done

Note: first argument is the new file name, the second argument is the new extension and the third argument is the directory which contains the files which are to be renamed. So the script will be called from command line with a command similar to this: ./rename.sh new_file pdf /home/dir/something/

Polb
  • 640
  • 2
  • 8
  • 21
  • 3
    I'd start by putting that script into http://shellcheck.net as it's littered with things that would be picked up there. I guess that what you're really looking for is something like `printf '%04d' "$i"` though. – Tom Fenech Jan 15 '16 at 12:24
  • http://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers – Ian2thedv Jan 15 '16 at 12:34

2 Answers2

4

Just keep a counter in a variable, use arithmetic expression to increment it after processing each file. Use command substitution with printf to create the zero padded number.

new=$1
ext=$2
dir=$3

id=1
for file in "$dir"/* ; do
    mv "$file" "$dir/$new"$(printf '%04d' $id)."$ext"
    (( id++ ))
done

You might need to only rename "$dir"/*."$ext" if there are files you don't want to rename with different extensions.

choroba
  • 231,213
  • 25
  • 204
  • 289
  • Is there any way to adjust the number of digits the index has? I would like to be able to use this script for a folder which contains, for instance, 7 files, 24 files, 114 file, 1000 files or even more. Can printf padding do that? I tryed to do something like `printf '%0$(nr_of_files)d $id'` but it does not seem to work – Polb Jan 15 '16 at 12:46
  • @Polb: You don't want the number of files, but the length of the number of files. Use `${#var}` to get the length of a variable's value. – choroba Jan 15 '16 at 13:02
  • Now I understand that what I said is wrong, I need the lenght of the number of files. But still, is there any way to specify something else than an explicit number in `printf`function? I want to insert the variable which holds the number of files instead of the constant value 4. Like `printf '%0$(variable)d $id'`. So my script should keep a constant number of character for the renamed files, in any directory. – Polb Jan 15 '16 at 13:41
  • @Polb: Yes, just use `printf "%0${#number_of_files}d" $id`. Parameter expansion doesn't work in single quotes, you need double quotes. – choroba Jan 15 '16 at 13:48
  • Thanks a lot, this is exactly what I wanted my script to do. – Polb Jan 15 '16 at 14:06
  • What would be wrong with `ls *.jpg | cat -n | while read n f; do mv "$f" "$(printf basename_%04d.txt $n)"; done` ? – Frank N Nov 05 '16 at 06:37
  • 1
    @FrankN: It doesn't work for `$'a\nb.jpg'` or `' file.jpg'`. – choroba Nov 05 '16 at 08:37
0

Here is my script, which works only on files, sorts them and renames them with numbers of right length (beginning with zeroes)

#!/bin/bash
dots=`find -maxdepth 1 -type f |wc -l|sed "s/./\./g"`
zeroes=`find -maxdepth 1 -type f |wc -l|sed "s/./0/g"`
(
    echo "x=0;zeroes=${zeroes};"
    find  -maxdepth 1 -type f  |sort |sed 's/.*/echo "mv \0 file${zeroes}$((x++)).txt"/'
)|bash|sed "s/\(file\)0*\(${dots}\.txt\)/\1\2/"

The scripts just types some mv something file0012.txt commands, so you either pipe that to bash, or add |bash to the end of the last line

Be also aware, that running such script more times on the same directory (after some modifications - maybe if you add file000000.txt) may result to garbage, as it would try to move files file12.txt to file13.txt possibly overwriting some of them on the way

gilhad
  • 609
  • 1
  • 5
  • 22