35

I am trying to change all the files names in a current folder and I am trying to achieve this either by removing the files prefix (every file has a common prefix) or changing their names to their count (if there are 5 files, the filenames will be 1.txt 2.txt 3.txt 4.txt 5.txt).

Now I have found the ren command in cmd and played with it a little but so far I was not able to achieve the result and I can only run this in cmd, so no batch files can be used.

This is the closest that I got, but it only adds a prefix:

FOR %f IN (*.*) DO ren %f prefix%f

I have tried doing the opposite:

FOR %f IN (*.*) DO ren prefix%f %f

But of course, didn't work so I am now asking for help and some explanation if possible (I like to understand how these things work). Thanks in advance for any help.

Shadow
  • 4,168
  • 5
  • 41
  • 72
  • These commands don't even seem to work well with very large directories. It keep adding prefix to files that it already added prefix to. – hnviet Nov 22 '12 at 20:19
  • I explained here it may help you : https://askubuntu.com/a/1376301/1392440 – BARIS KURT Mar 06 '22 at 21:45

4 Answers4

72

A much simpler solution is provided in
https://superuser.com/a/871799/497147

I copied it here for easier access.

Forget about complicated scripts for this.

rename is a very old and never properly completed command. If you do not use it properly, the result might surprise you.

For example to remove a prefix abcd from abcd1.txt, abcd2.txt, abcd3.txt etc. in order to get 1.txt, 2.txt, 3.txt simply use

rename "abcd*.txt" "////*.txt"

You need the same number of / as the number of initial characters you would like to remove.

Do place double quotes for both arguments.

Community
  • 1
  • 1
Alnair
  • 938
  • 8
  • 10
  • 1
    Saviour of the day. – gilad905 Apr 10 '17 at 21:51
  • Very cool and bizarre technique. I've updated my [How does the Windows RENAME command interpret wildcards?](https://superuser.com/q/475874/109090) SuperUser Q&A with this information, though technically, the `/` is not functioning as a wild card. – dbenham Jun 03 '17 at 19:21
  • 3
    Incredibly simple and perfectly working. Note that number of "/" is not related to how many chars are specified in matching expression. Another example: `rename "IM*.*" "////*.*"` is matching on a 2-char prefix and removing 4 chars – PaoloC Oct 24 '17 at 21:33
  • I use this to remove the `IMG-` prefix of WhatsApp images: `rename "IMG-*.*" "////*.*"` – mihca Jul 25 '21 at 14:51
  • The forward slashes only work for **leading** characters. They cannot be used at any other position in the to be renamed file name. Else error "The system cannot find the file specified." will appear. – René K Oct 06 '22 at 22:12
43

I don't understand why you can't use a batch file. But here is a solution that should work with most file names.

Critical - first you must make sure you have an undefined variable name, I'll use fname

set "fname="

Next is the command to actually do the renaming. It won't work properly if fname is already defined.

for %a in (prefix*.txt) do @(set "fname=%a" & call ren "%fname%" "%fname:*prefix=%")

The fname variable is defined for each iteration and then the syntax %fname:*prefix=% replaces the first occurrence of "prefix" with nothing. The tricky thing is Windows first attempts to expand %fname% when the command is first parsed. Of course that won't work because it hasn't been defined yet. On the command line the percents are preserved if the variable is not found. The CALL causes an extra expansion phase that occurs after the variable has been set, so the expansion works.

If fname is defined prior to running the command, then it will simply try to rename that same file for each iteration instead of the value that is being assigned within the loop.

If you want to run the command again with a different prefix, you will have to first clear the definition again.

EDIT - Here is a batch file named "RemovePrefix.bat" that does the job

::RemovePrefix.bat  prefix  fileMask
@echo off
setlocal
for %%A in ("%~1%~2") do (
  set "fname=%%~A"
  call ren "%%fname%%" "%%fname:*%~1=%%"
)

Suppose you had files named like "prefixName.txt", then you would use the script by executing

RemovePrefix  "prefix"  "*.txt"

The batch file will rename files in your current directory. The batch file will also have to be in your current directory unless the batch file exists in a directory that is in your PATH variable. Or you can specify the full path to the batch file when you call it.

The rules for expansion are different in a batch file. FOR variables must be referenced as %%A instead of %A, and %%fname%% is not expanded initially, instead the double percents are converted into single percents and then %fname% is expanded after the CALL. It doesn't matter if fname is already defined with the batch file. The SETLOCAL makes the definition of fname temporary (local) to the batch file.

dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Perfect, thank you very much for the additional explanation as well! Edit: Just as an extra request, could you post an example if it could be made in a batch file? – Shadow Apr 18 '12 at 05:03
  • I don't know how it was perfect - there was a nasty bug where %f was getting confused with the %f in %fname%. All fixed now :) – dbenham Apr 18 '12 at 12:12
  • What modification I must make in this script such that it searches for `".txt"` in every child directory of the current directory and removes the given `prefix`? – Kushal May 20 '12 at 17:34
  • I believe you only need to add the /R option to the FOR statement – dbenham May 20 '12 at 18:28
-1

You can do it this way (let's say your prefix is "AS"):

x=1; for k in AS*; do y=$((x++));  echo "mv ${k} ${k:0:2}$y.txt"; done

if you want to save extensions use this (pre-test):

x=1; for k in AS*; do y=$((x++));  echo "mv ${k} ${k:0:2}$y.${k#*.}"; done

if pre-test is OK then remove echo and code will run this time:

x=1; for k in AS*; do y=$((x++));  mv ${k} ${k:0:2}$y.txt; done

*for saving extensions (remove echo and code will run this time):

x=1; for k in AS*; do y=$((x++));  mv ${k} ${k:0:2}$y.${k#*.}; done
  • ${k:0:2} --> first two letters of file 0 to 2...
  • ${k#*.}--> extension of the file

I had a similar situation myself and solved it.

My files were like this:

 1-6-4-20.txt       onar.mol2  replace.py  z.out       z__06.mol2  z__09.mol2  z__12.mol2  z__15.mol2  z__18.mol2  z__27.mol2  z__30.mol2  z__33.mol2  z__36.mol2
make_com_files.py  pt.dat     valid.txt   z.xyz       z__07.mol2  z__10.mol2  z__13.mol2  z__16.mol2  z__25.mol2  z__28.mol2  z__31.mol2  z__34.mol2  z__37.mol2
makepymol.py       pymol.pml  x.py        z__05.mol2  z__08.mol2  z__11.mol2  z__14.mol2  z__17.mol2  z__26.mol2  z__29.mol2  z__32.mol2  z__35.mol2

Note that there is no z_01.mol2 z_02.mol2 z_03.mol2 z_04.mol2 and z_19.mol2 z_20.mol2 etc.. so my z files are not in sequence. I can't get rid of the problem by omitting the z_* prefix. and also I have onar.mol2

Here is my solution:

pre-test using echo to see if it is working correctly:

 x=1; for k in *.mol2; do y=$((x++));  echo "mv ${k%%.*}.mol2 $y.mol2"; done

output:

mv onar.mol2 1.mol2
mv z__05.mol2 2.mol2
mv z__05.mol2 2.mol2
    mv z__06.mol2 3.mol2
    mv z__07.mol2 4.mol2
    mv z__08.mol2 5.mol2
    mv z__09.mol2 6.mol2
    mv z__10.mol2 7.mol2
    mv z__11.mol2 8.mol2
    mv z__12.mol2 9.mol2
    mv z__13.mol2 10.mol2
    mv z__14.mol2 11.mol2
    mv z__15.mol2 12.mol2
    mv z__16.mol2 13.mol2
    mv z__17.mol2 14.mol2
    mv z__18.mol2 15.mol2
    mv z__25.mol2 16.mol2
    mv z__26.mol2 17.mol2
    mv z__27.mol2 18.mol2
    mv z__28.mol2 19.mol2
    mv z__29.mol2 20.mol2
    mv z__30.mol2 21.mol2
    mv z__31.mol2 22.mol2
    mv z__32.mol2 23.mol2
    mv z__33.mol2 24.mol2
    mv z__34.mol2 25.mol2
    mv z__35.mol2 26.mol2
    mv z__36.mol2 27.mol2
    mv z__37.mol2 28.mol2

seems correct then I can use this as a command for my aim (by removing echo):

x=1; for k in *.mol2; do y=$((x++));  mv ${k%%.*}.mol2 $y.mol2; done

RESULT: ls -ln:

-rwxrwxrwx 1 0 0     1695 Nov 18 12:07 1-6-4-20.txt
-rwxrwxrwx 1 0 0     1813 Nov 18 13:27 1.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 10.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 11.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 12.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 13.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 14.mol2
-rwxrwxrwx 1 0 0     2784 Nov 18 13:27 15.mol2
-rwxrwxrwx 1 0 0     2785 Nov 18 13:27 16.mol2
-rwxrwxrwx 1 0 0     2785 Nov 18 13:27 17.mol2
-rwxrwxrwx 1 0 0     2786 Nov 18 13:27 18.mol2
-rwxrwxrwx 1 0 0     2786 Nov 18 13:27 19.mol2
-rwxrwxrwx 1 0 0     2781 Nov 18 13:27 2.mol2
-rwxrwxrwx 1 0 0     2787 Nov 18 13:27 20.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 21.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 22.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 23.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 24.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 25.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 26.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 27.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 28.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 3.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 4.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 5.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 6.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 7.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 8.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 9.mol2
-rwxrwxrwx 1 0 0     1383 Nov 17 12:27 make_com_files.py
-rwxrwxrwx 1 0 0     5687 Nov 17 16:34 makepymol.py
-rwxrwxrwx 1 0 0     1206 Nov 17 11:36 pt.dat
-rwxrwxrwx 1 0 0      964 Nov 18 13:29 pymol.pml
-rwxrwxrwx 1 0 0     2288 Nov 18 13:27 replace.py
-rwxrwxrwx 1 0 0     1284 Nov 18 13:07 valid.txt
-rwxrwxrwx 1 0 0     3809 Nov 18 12:37 x.py
-rwxrwxrwx 1 0 0 19622334 Nov 18 04:11 z.out
-rwxrwxrwx 1 0 0    34717 Nov 18 12:37 z.xyz
    enter code here

EXTRA:
and if I want my files as 00001.mol2 00002.mol2 etc, I can add this command too:

rename 's/\d+/sprintf("%05d",$&)/e' *.mol2

Here are my mol2 files:

-rwxrwxrwx 1 0 0     1813 Nov 18 13:27 00001.mol2
-rwxrwxrwx 1 0 0     2781 Nov 18 13:27 00002.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 00003.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00004.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00005.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00006.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00007.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 00008.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 00009.mol2
-rwxrwxrwx 1 0 0     2782 Nov 18 13:27 00010.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00011.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00012.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00013.mol2
-rwxrwxrwx 1 0 0     2783 Nov 18 13:27 00014.mol2
-rwxrwxrwx 1 0 0     2784 Nov 18 13:27 00015.mol2
-rwxrwxrwx 1 0 0     2785 Nov 18 13:27 00016.mol2
-rwxrwxrwx 1 0 0     2785 Nov 18 13:27 00017.mol2
-rwxrwxrwx 1 0 0     2786 Nov 18 13:27 00018.mol2
-rwxrwxrwx 1 0 0     2786 Nov 18 13:27 00019.mol2
-rwxrwxrwx 1 0 0     2787 Nov 18 13:27 00020.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00021.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00022.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00023.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00024.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00025.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00026.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00027.mol2
-rwxrwxrwx 1 0 0     2788 Nov 18 13:27 00028.mol2
-rwxrwxrwx 1 0 0     1695 Nov 18 12:07 1-6-4-20.txt
-rwxrwxrwx 1 0 0     1383 Nov 17 12:27 make_com_files.py
-rwxrwxrwx 1 0 0     5687 Nov 17 16:34 makepymol.py
-rwxrwxrwx 1 0 0     1206 Nov 17 11:36 pt.dat
-rwxrwxrwx 1 0 0      964 Nov 18 13:29 pymol.pml
-rwxrwxrwx 1 0 0     2288 Nov 18 13:27 replace.py
-rwxrwxrwx 1 0 0     1284 Nov 18 13:07 valid.txt
-rwxrwxrwx 1 0 0     3809 Nov 18 12:37 x.py
-rwxrwxrwx 1 0 0 19622334 Nov 18 04:11 z.out
-rwxrwxrwx 1 0 0    34717 Nov 18 12:37 z.xyz
BARIS KURT
  • 477
  • 4
  • 15
-2

Following is straight way to trim the prefix with rename for all the files

rename -d your_prefix *
Tamer
  • 91
  • 2
  • 10