15

How to rename file as below

AS1100801000002.RAW7AGS 
AS1100801001008.RAW7AH4
AS1100801002001.RAW7AH9
AS1100801003002.RAW7AHE
AS1100801004009.RAW7AHT
AS1100801005002.RAW7AHY
AS1100801010002.RAW7AJ3

to new name

AS1.txt
AS2.txt
AS3.txt
AS4.txt
AS5.txt
AS6.txt
AS7.txt
0

7 Answers 7

24

The rename tool that ships with Ubuntu is pretty hot at this sort of stuff. You can embed little Perl expressions like so:

rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' *

That will just show you what it would do. Remove the -n to make it a live-fire exercise.

This basically works by rough-defining a variable and incrementing it each file we hit. If you're going to have more than 10 files, I suggest using some zero-padding in the sprintf. The following is good up to 999:

rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' *

... But that's easy enough to expand.

0
4

I don't know of a single command or utility that would do this, but it's easy enough to do with a simple loop:

N=1
for X in AS*RAW*; do
  mv $X AS$N.txt
  N=$(($N+1))
done
3

To improve on @Oli's answer, the rename tool version 1.600 by Aristotle Pagaltzis actually has a counter built in, $N.

So all you need is,

rename 's/AS.*/AS$N/' *

To install,

  1. brew install rename or Download the script
  2. Save it to a directory on your system path (usually /usr/local/bin/brew or /usr/bin)
2
  • 3
    This seems to be a different tool with the same name. Ubuntu's default rename is prename. This may be better but you might want to add installation instructions to make this answer more valuable.
    – Oli
    Feb 15, 2018 at 17:17
  • 1
    @Oli good call! updated.
    – Atav32
    Feb 15, 2018 at 20:03
2

rename lets you assign directly to $_, which is ideal for this problem.

Although the code arguments we pass to the Perl rename utility often perform matching and substitution (with s/), and it is totally acceptable to solve this problem that way, there's really no need for that in cases like this one where you're not actually examining or reusing the text of the old filenames. rename lets you write just about any Perl code, and it doesn't need to be embedded inside s/ /e. I suggest using a command like this:

rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *

Or, if you feel like shaving off a few characters:

rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *

(It could be made even shorter, but not without sacrificing clarity.)

Both those commands do the same thing. Each shows what renaming operations would be undertaken. Once you try one out and you're happy with the results, run it again without the -n option. As written, this would produce the filenames AS01.txt, AS02.txt, ..., AS10.txt, AS11.txt, and so on. You can modify them as needed, then only remove -n when you like what you see.

If you want to pad to a greater width than 2, replace the 2 with a bigger number. For example, if for some reason you wanted filenames like AS00000000000001.txt, you would replace %02d with %014d. If you don't want padding at all--even though that would make your files appear in non-numeric order when you list them later!--then you can replace %02d with just %d.

How does this work? Your shell expands * into a list of files before it even runs the rename command. The list is sorted lexicographically (i.e., alphabetically) according to your current locale settings. rename receives the filenames as command-line arguments and processes them in the order they are listed. The expression ++$i evaluates to one greater than the current value of the variable $i, and also sets the variable $i to that newly incremented value. This value is passed to sprintf, which formats it and places it inside other text. This text is assigned directly to the special variable $_, which holds the filename. Since the rename processes files in the order they are passed as arguments, they are numbered accordingly.


You may have noticed the similarity to Oli's answer!

Both declare and increment a counter variable, and both use sprintf in essentially the same way to embed the value of that counter, padded on the left with zeros, in the other text of the new filenames. (The information in either answer about how to pad with zeros--and change the padding width--even applies equally to both.) The reason they are so similar is that the method in that older answer is really doing just this1, but with extra steps that are useful for many problems but not actually necessary for this one.

For comparison, here's what the second command in that answer looks like if modified to use the style I've used here (and to pad to a width of 2, as I've done here, instead of 3):

rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *

The part between s/.+/ and /e in that command is now the same as the expression I assign to $_ (i.e., the code on the right side of the = operator) in the first command in this answer.

  • The s/ operator attempts to match text (filenames that your shell expanded from * and passed as command-line arguments when it ran rename) with a regular expression, and performs substitution. / is being used as a delimiter to separate the different parts of the s expression. The first part, .+, is the regular expression; it matches any1 character (.), and does so one or more times (+). Since filenames are never empty--they're always at least one character long--this is one way to match any1 filename.
  • Then it produces text from each match--that is, from each whole filename--consisting of our $i; sprintf "AS%02d.txt", ++$i. This produces the new filename. Typically, one uses s/ to produce text that is either (a) replacing text that matched just part of the filename, or (b) based on the the matched text in some way (for example, it might use a special variable like $& that expands to the match). In this case, though, the matched text is not being used at all.
  • Normally the substituted text our $i; sprintf "AS%02d.txt", ++$i would be used as a filename, not run as code. But the /e flag at the end causes that text to be treated as Perl source code and evaluated, and uses the value produced by doing so (in this case, the return value of Perl's built-in sprintf function) as the new filename.

Although I think the method I've shown here is a clearer and simpler approach for this problem than any method that uses s/ with /e, it's good to be aware of that technique, because it is well suited to a number of other file renaming problems where all or part of the original filenames is examined and/or retained. I recommend this blog post by Oli (who also wrote that answer), which includes some such examples.

1 Technically, there is a difference in the behavior of the $_ = commands and the s/ /e commands. In the regular expression .+, it's not strictly true that . matches any character, because it does not match a newline. You very probably shouldn't use filenames with newlines in them, but you can, and occasionally a file gets named that way by accident. If you feel like it, contrast the output of rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar' to that of rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'. To make . match a newline, use the s flag, which goes at the end (with e). That is, write /se at the end instead of /e.

1

Though the OP requires a command line option, it is also available as a GUI option in Nautilus and is quite easy.

Select all the required files and press F2. There is an option called Automatic Numbers. You can append it to the text that you need.

0

Suppose the files you want to rename are in ~/Adir, and these are the only files in this folder, then:

n=0
for f in $( ls ~/Adir | sort ) ; do
    n=$(( n+1 ))
    mv -n "$f" "AS${n}.txt"
done

This script will look at each file in ~/Adir and rename it to AS1.txt, AS2.txt, ... if the file does not exists (there won't be any overwritting). That's why you should make sure these are the only files in ~/Adir. The sort command is just in case you want the files to keep the initial order.

0

You can do it this way:

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
  • ${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
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.