Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to rename all files in a directory. The new names don't follow any pattern, so I can't use rename. Is there any efficient way to do this, so I won't have to use mv foo.txt bar.txt for every single file?

share|improve this question
    
If the new names do not follow any pattern the only thing you can do is list the directory contents to a file and then edit the file to suit. –  suspectus May 9 '13 at 16:25
    
You could write your own BASH script to ask for a new name for each file –  wolfo9999 May 9 '13 at 16:30
5  
By sheer luck I discovered imv (from renameutils) which allows you to interactively rename a file. But that will only accept one file, so you need a loop: for file in *; do imv "$file"; done. –  Bobby May 9 '13 at 16:33
    
Thanks Bobby, that's exactly what I've been looking for. Could you post it as an answer, please, so I can upvote you properly? –  n.st May 9 '13 at 16:37
1  
Pinging @Bobby (n.st, you need to explicitly @-mention users in order for them to receive a notification.) –  slhck May 9 '13 at 20:48
add comment

3 Answers

up vote 3 down vote accepted

When thinking about writing this as a script I checked if possible names are already taken, and turns out my guess "interactive move" is already written and ready to use. For most systems it should be available in the renameutils-package, which contains various tools which are very helpful:

  • qmv/qcp: Quick Move/Copy, writes all filenames to a text file which then can be edited.
  • imv/icp: Interactive Move/Copy, asks for the new name of the files.

The problem with imv/icp in this case is, that those only accept one argument:

imv FILENAME

Multiple arguments will yield an error. So you'll basically have to wrap it up in a short for loop:

for file in *; do imv "$file"; done

That is of course hard to type, so we should wrap this into a ready to use function which we can place in our .bashrc file.

# Mass Interactive Move
function mimv {
    for file in "$*"; do
        imv "$file"
    done
}

Fortunately, imv shows the name of the file which is currently process, so we don't need any echo statement in there so that we know what is going on.

share|improve this answer
add comment

You can use this command:

for i in *; do
   read -p "$i -> " newname
   if [[ ! -z "$newname" ]]; then
      mv -v -- "$i" "$newname"
   fi
done

It will prompt you for a new name for every file and also for every directory (for i in *) in the current directory. The new name gets read into $newname. If you hit Enter without typing in a new name, nothing is done (-z $newname checks, if $newnameis empty (zero); ! is logical not), otherwise mv is used to rename the file.


If you want to change the file name only a little bit, it's more efficient if you can edit it, starting with the old file name, as suggested by @grawity:

for i in *; do
   read -p "$i -> " -e -i "$i" newname
   if [[ ! -z "$newname" ]]; then
      mv -v -- "$i" "$newname"
   fi
done

I tested it with filenames containing spaces and braces, however please use it on your own risk (and make a backup of the original files before).

share|improve this answer
2  
Heh, you were faster. And you did test with spaces in the names, which I forgot. –  Hennes May 9 '13 at 16:49
1  
If you use read -p "$i -> " -e -i "$i" newname, it'll let you edit the old name directly. –  grawity May 9 '13 at 16:55
    
@Hennes: I was trained by a comment by slhck (superuser.com/questions/593396/…) earlier that day ;) –  mpy May 9 '13 at 16:55
    
@grawity: Thanks, that's a neat trick -- I incorporated it into my answer. –  mpy May 9 '13 at 17:04
    
@mpy: except you didn't, -e -i "$i" is the key part :D –  grawity May 9 '13 at 17:13
show 3 more comments
#!/usr/bin/env bash

for files in $( echo * );
do
     echo -n Rename $files  to which name? ;
     read new_name ;
     mv "$files" "$new_name";
done
share|improve this answer
1  
for files in $(echo *) is very redundant – it could be replaced with for files in *, which even works properly with spaces in names. –  grawity May 9 '13 at 16:58
    
Aye. i used it in an earlier version. One which asked for a pattern of files so you could just use ./q testfile to rename all files matching testfile*. I cut those parts out before posting. (It was not as nice as mpy's answer is atm, but I do like to add small things such as if [ -z $1 ] ; then echo Usage: $0 files to rename exit fi –  Hennes May 9 '13 at 17:07
    
if [ -z "$1" ] –  grawity May 9 '13 at 17:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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