2

How to rename multiple files starting from 1 to unlimited ( to finish all files ) ?

My files looks like:

file.jpeg.jpg
fileA.jpeg.jpg
fileB.jpeg.jpg

Output:

1.jpeg.jpg
2.jpeg.jpg
3.jpeg.jpg

I'm using Cygwin so I can't install packages

Abudayah
  • 123

4 Answers4

2

Try:

n=0; for f in *.jpg; do mv "$f" "$((++n)).jpeg.jpg"; done

Or, the same thing spread out over multiple lines:

n=0
for f in *.jpg
do
    mv "$f" "$((++n)).jpeg.jpg"
done

How it works

  • n=0

    This initializes the variable nn.

  • for f in *.jpg; do

    This starts a loop over all files in the current directory whose names end with .jpg.

  • mv "$f" "$((++n)).jpeg.jpg"

    This renames the files as you want. In bash, $((...)) does arithmetic. Here, we have it increment n each time it is run.

  • done

    This signals the end of the loop.

This code will work even if there are files whose names contain spaces, tabs, newlines, or other difficult characters.

The Order

The glob test*.in is expanded into a list of files in alphabetical order. This is documented in man bash:

bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of filenames matching the pattern (see Pattern Matching below). [Emphasis added.]

Note that the meaning of alphabetical sorting may depend on your locale setting.

John1024
  • 74,655
1
j=0;
for i in `ls`
do
     mv $i $j.jpeg.jpg
     j=`echo $j + 1 | bc`
done
SHW
  • 14,786
  • 14
  • 66
  • 101
1

Since the number of files can be "unlimited", there is a builtin limit to the size of the command line. See https://stackoverflow.com/questions/19354870/bash-command-line-and-input-limit . Therefore, I would use find to solve this. E.g, in bash:

cd /path/to/directory
n=1
find . -maxdepth 1 -type f -name "*.jpeg.jpg" | sort |  while read file; do
    mv "$file" $n.jpeg.jpg
    let n=n+1
done

The steps are as follows, line-by-line:

  1. Change to the appropriate directory
  2. Set the file counter to 1
  3. find in the . (current) directory, and do not burrow into any subdirectories (-maxdepth 1), and look at only regular files -type f, and return only files whose name matches the pattern *.jpeg.jpg, and print their names (by default). Pipe the output of the find command to the sort command so they are in order (sort can handle very large stdin). Pipe the output of sort to a while/read loop, which will set each line of input to the variable file, line by line.
  4. Move the file whose name is stored in the file variable to a file named by the $n variable, concantenated with the string `.jpeg.jpg'
  5. Increment the variable n
  6. Loop to the next filename.

You can handle a very large directory this way. It's fairly immune to 'weird' (aka "characters not in the printable ASCII set") file names. It can be made even more immune but that's probably unnecessary for this case, I'm guessing (It involves using the -print0 option, and probably the xargs command).

Mike S
  • 2,502
  • 2
  • 18
  • 29
  • Actually, I found that I fret too much. From me answer here: http://stackoverflow.com/questions/19354870/bash-command-line-and-input-limit/33619281#33619281 , we can see that a for loop as posted here above by @John1024 can handle a very large group of files. I don't know how large... my tests showed 500,000 files of 18 characters each are handled just fine. – Mike S Nov 09 '15 at 22:15
0

This version will keep the new files in the same order when you list them aphabetically (as in the output of ls):

#!/bin/sh
i=0
for f in *.jpeg.jpg
do
     mv "$f" "$(printf '%011d.jpeg.jpg' $i)"
     i=$(expr $i + 1)
done
RobertL
  • 6,780