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
22

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.

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)
  • 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 '18 at 17:17
  • 1
    @Oli good call! updated. – Atav32 Feb 15 '18 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.

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

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.

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.