for file in *; do read line;  mv -v "${file}" "${line}";  done < /var/www/html/uploads/songs.txt

It works as in changing all 700 files. But it doesn't seem to do it in the correct order. I feel like it's changing the order as it renames them or something I'm not 100% sure.

Here is an example: First File is:

/var/www/html/uploads/Music/A.D.I.D.A_S - Live (Korn Live).mp3_Rare_2006_.mp3

First in the text file that it should be renamed to:


Like I said all of them get renamed and a lot of them match. Typically the first and last few. The middle however seems to not stay in the appropriate order and end up getting another files name.

  • ls * >list.txt will produce a list of the file in the order in which they will be processed (because the '*' will be expanded exactly in the same way as in your command). Does this match your file? – xenoid Mar 16 '19 at 9:23
  • What's the significance of /var/www/html/uploads/songs.txt? It looks as if you just want to modify the existing filename by translating some punctuation characters... – Kusalananda Mar 16 '19 at 10:41
  • I'm voting to close this as unclear until such time that further information is added regarding the contents of the file that you read. – Kusalananda Mar 16 '19 at 17:31

IMHO a very dangerous technique, you are at the mercy of any change in the directory (files added/deleted). A much safer technique is to list pairs of old/new names, and either:

  • iterate the existing files, using grep to retrieve the new name
  • load the whole list in an associative array (in recent version of bash, arrays can use string indices)
  • forego all that complexity, just add `mv`` at the beginning of lines in the list, and use it as a script

You can generate the list of pairs using:

ls pattern_for_old* | paste - list_of_new_names >combined.lst

(incidentally, just generating this list can show you where your current problem is...)

| improve this answer | |

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