[SOLVED] Moving files, on shell, auto-renaming in a "basename(##).ext" pattern?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Moving files, on shell, auto-renaming in a "basename(##).ext" pattern?
Just like google chrome does when you download something with the same name, or just as konqueror file manager can do, after a dialog. But I was looking for something to do that via command line.
Is there such a thing? I'm a bit surprised that it seemingly doesn't.
Would be nice if there was something like "konqueror-mv --autorename *.ext /somewhere/else/", but I feel that's unlikely, even with all those "dcop" things.
The closest thing I've found so far is the "backup" function of mv, but it renames the original as a backup, not the new one, and the renamed files are in an ugly/somewhat dysfunctional pattern, "file-yadda1yadda2.ext~123~", overriding the extension.
I was trying to come up with some script, but it would probably take quite a bit of time to figure it out, so I thought it wouldn't hurt to ask. Perhaps I was just having bad luck with google (... and by that I don't mean that I only tried the "I'm feeling lucky" button, which I never tried anyway).
You might need to explain further under what circumstances you wish this renaming to occur?
Are we simply talking about moving a file to a new location and it already exists? Or is this some kind of backup process in which many files are being moved and all / some / none may exist?
If you don't care about all the edge cases, implementation of such a command would be rather easy. Here's a (not tested) function that operates on a single file and requires the second argument to be a directory:
Code:
mv_file() {
src=$1
filename=${src##*/}
dest_dir=$2
if ! [ -e "$dest_dir/$filename" ]; then
mv "$src" "$dest_dir/$filename"
return $?
fi
case $filename in
*.*)
ext=.${filename##.*}
;;
*)
ext=
esac
base=${filename*.%}
n=1
while [ -e "$dest_dir/$base~$n$ext" ]; do
n=$(( $n + 1 ))
done
mv_file "$src" "$dest_dir/$base~$n$ext"
}
You might need to explain further under what circumstances you wish this renaming to occur?
Are we simply talking about moving a file to a new location and it already exists? Or is this some kind of backup process in which many files are being moved and all / some / none may exist?
The second. But I'm thinking more about the file name being the same, and the files themselves being different.
In konqueror, it simply points that a given file you're trying to move or copy already exists in that destination. Then it asks whether you want to skip, automatically rename the moved file, or overwrite the file on the target folder. And it gives the option to always follow the same option. Bash's "mv *.pdf" will only ask whether you want to overwrite or skip, for each individual file. Unless you pipe it to "yes", but it still wouldn't rename automatically.
I'm thinking only about the end-user user-friendliness aspect, I didn't think of some sort of important ramification for system administration or any other sort of more serious business.
If you don't care about all the edge cases, implementation of such a command would be rather easy. Here's a (not tested) function that operates on a single file and requires the second argument to be a directory:
Code:
mv_file() {
src=$1
filename=${src##*/}
dest_dir=$2
if ! [ -e "$dest_dir/$filename" ]; then
mv "$src" "$dest_dir/$filename"
return $?
fi
case $filename in
*.*)
ext=.${filename##.*}
;;
*)
ext=
esac
base=${filename*.%}
n=1
while [ -e "$dest_dir/$base~$n$ext" ]; do
n=$(( $n + 1 ))
done
mv_file "$src" "$dest_dir/$base~$n$ext"
}
Thanks. I'll check that. Before I was trying to come up with something to deal with many files at once. For individual files I think "mv -i" as an alias for "mv" (if you forget it) suffices, then you just rename "manually" as you issue mv again. Perhaps it could be effective if something like an automatic rejection of "mv -i" could be used to create a list of the conflicting names, create new suffixes for them in a loop that checks if the name already exists, and finally move when they don't. To make even fancier I was thinking of trying to "grep" a "(##).ext" pattern and add numbers to that. Then I thought it perhaps something like that already existed, and probably better and safer than something I'd come up with in Bash.
You can use this function in a loop to handle multiple files. Just wrap it in a loop.
Quote:
Originally Posted by the dsc
I think "mv -i" as an alias for "mv" (if you forget it) suffices
Personally I advice against it. If you get used to the fact that “mv” asks you questions, then day will come when you sit in front of a computer where this alias is not defined, you you'll overwrite some important data. Either remember to add “-i” whenever you need or create a new command such as “mi”.
As for me, I am always too-afraid of shooting myself in the foot. So, I like to do things like this more slowly. First, use ls to create a list of files. Then, use sed (say ...) to edit that file to turn it into a list of mv ("rename") commands. Then, ("abandon all hope, ye who screw-up here!!")Look at it!! (Take a nice walk and look at it again.) Then, execute that file as a script.
Been there, done that ... (But then again, I am also a punched-card carrying member of the "dropped an entire box of cards onto the floor" club.) Computer technology has an amazing ability to make a total and irrecoverable mess of things in a remarkably short amount of time.
Last edited by sundialsvcs; 12-02-2013 at 01:45 PM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.