4

This question already has an answer here:

Let's say I have these files in my folder:

cat.txt
dog.txt
house.txt
tree.txt

I want to rename all of them to something like this:

file1.txt
file2.txt
file3.txt
file4.txt

Is that possible to do via the command line?

I've only seen questions about renaming files that have some kind of pattern, like rename dog1.txt, dog2.txt -> cat1.txt, cat2.txt.

marked as duplicate by αғsнιη, waltinator, Sergiy Kolodyazhnyy command-line Jul 22 '17 at 4:45

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

5

Use rename utility to do this:

rename -n '$_ = sprintf "file%d.txt", ++$::count' *

Notes

  • -n makes the command show you what will happen if you run it. If the output was what you want, run it without -n to actually rename the files.
  • replace the * with what you want to rename, for example: dog*.txt to only rename dog1.txt, dog2.txt ... to file1.txt, file2.txt, etc.
  • $_ is a default input (file names) which we should modify.
  • using = we are modifying it
  • with sprintf we are defining a schema started by file followed by %d means a number and ended to the .txt.
  • the number (%d) will be assigned using ++$::count, which is a simple counter iterated after each rename.

The idea comes from here.

  • It worked! Thank you. It was the simplest method I've seen. Well, I'm not a developer guy, so could you explain a little the part -> '$_ = sprintf "file%d.txt", ++$::count' ? What I understand is the files will be renamed like file1, file2 etc because of the "file%d.txt", but the rest of the code I'm trying to understand. Thanks. – Denis Alves Jul 21 '17 at 19:53
  • @DenisAlves Updated the answer. – Ravexina Jul 21 '17 at 20:15
2

It may be done, but with some caveats. You have stated that "...these files [are] in my folder", which would be one of such caveats. We could use globstar and iterate over the expanded filenames:

$ c=0;for f in *; do ((c++));  echo "$f" "--->" file"$c".txt ; done                            
cat.txt ---> file1.txt
dog.txt ---> file2.txt
house.txt ---> file3.txt
tree.txt ---> file4.txt

Of course you could always go the "manual" way via a list.txt, where you can store a list of filenames and read that file via the while IFS= read -r ; do ... done < list.txt

$ c=0; while IFS= read -r f; do ((c++)); echo "$f" file"$c" ; done < input.txt                 
cat.txt file1
dog.txt file2
tree.txt file3

Of course this list theme can be extended in many ways - csv lists, json files,key-value lists - you name it. There's plenty of questions about these online. There's of course other choices you have to make, like give full path to files or perform everything in the same directory as the list.

Finally, I already hinted at key-value lists. With bash and other more modern scripting languages like Python or Perl, you could have a hash ( or dictionary ) with list of files and corresponding new name that you wish the file to have.

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