2

In Linux how do I move files without replacing if a particular file already exists in the destination?

I tried the following command:

mv --backup=t <source> <dest>

The file doesn't get replaced but the issue is the extension gets changed because it puts "~" at the back of the filename.

Is there any other way to preserve the extension but only the filename gets changed when moving?

E.g. test~1.txt instead of test.txt~1

When the extension gets replaced, subsequently you can't just view a file by double clicking on it.

1
  • 1
    I presume you are aware of the -n option to mv? That's not quite what you're asking for (because it does nothing at all if the destination exists) but might be what you need... Commented Jan 25, 2016 at 10:14

4 Answers 4

5

If you want to make it in shell, without requiring atomicity (so if two shell processes are running the same code at the same time, you could be in trouble), you simply can (using the builtin test(1) feature of your shell)

[ -f destfile.txt ] || mv srcfile.txt destfile.txt

If you require atomicity (something that works when two processes are simultaneously running it), things are quite difficult, and you'll need to call some system calls in C. Look into renameat2(2)

Perhaps you should consider using some version control system like git ?

Sign up to request clarification or add additional context in comments.

1 Comment

OP wants to rename the files without touching their extension. This does not answer the question.
3

mv has an option:

-S, --suffix=SUFFIX
          override the usual backup suffix

which you might use; however afaik mv doesn't have a functionality to change part of the filename but not the extension. If you just want to be able to open the backup file with a text editor, you might consider something like:

mv --suffix=.backup.txt <source> <dest>

how this would work: suppose you have

-rw-r--r-- 1 chris users    2 Jan 25 11:43 test2.txt                                                                                                                                                                                                                           
-rw-r--r-- 1 chris users    0 Jan 25 11:42 test.txt

then after the command mv --suffix=.backup.txt test.txt test2.txt you get:

-rw-r--r-- 1 chris users    0 Jan 25 11:42 test2.txt                                                                                                                                                                                                                           
-rw-r--r-- 1 chris users    2 Jan 25 11:43 test2.txt.backup.txt

6 Comments

I'm pretty sure that mv (and similar tools such as cp and ln) never interprets filenames in any way. So it doesn't treat . with any particular significance, and the only transform it will ever do is to append a backup suffix. This is a Good Thing. If you want something different, then a Bash or Perl script is likely the way to go.
@TobySpeight I'm not saying that mv interpretes anything. I say clearly " afaik mv doesn't have a functionality to change part of the filename but not the extension". I added an example to illustrate my proposition; but I agree it isn't 100% what aandroidtest wanted.
I'm not arguing - my comment was a supplement to your answer. Just extra information for the questioner to explain why mv can't preserve the existing suffix. Sorry if it appeared that I was disputing your answer!
@TobySpeight I wasn't offended :) just thought my answer wasn't clear enough or that I missed something...
afaik; it is not possible unless you start writing a script yourself; along the lines of the suggestion of Basile...
|
1

@aandroidtest: if you are able to rely upon a Bash shell script and the source directory (where the files reside presently) and the target directory (where you want to them to move to) are same file system, I suggest you try out a script that I wrote. You can find it at https://github.com/jmmitchell/movestough

In short, the script allows you to move files from a source directory to a target directory while taking into account new files, duplicate (same file name, same contents) files, file collisions (same file name, different contents), as well as replicating needed subdirectory structures. In addition, the script handles file collision renaming in three forms. As an example if, /some/path/somefile.name.ext was found to be a conflicting file. It would be moved to the target directory with a name like one of the following, depending on the deconflicting style chosen (via the -u= or --unique-style= flag):

  • default style : /some/path/somefile.name.ext-< unique string here >
  • style 1 : /some/path/somefile.name.< unique string here >.ext
  • style 2 : /some/path/somefile.< unique string here >.name.ext

Let me know if you have any questions.

Comments

1

Guess mv command is quite limited if moving files with same filename.

Below is the bash script that can be used to move and if the file with the same filename exists it will append a number to the filename and the extension is also preserved for easier viewing.

I modified the script that can be found here: https://superuser.com/a/313924

#!/bin/bash
source=$1
dest=$2

file=$(basename $source)
basename=${file%.*}
ext=${file##*.}

if [[ ! -e "$dest/$basename.$ext" ]]; then
      mv "$source" "$dest"
else
      num=1
      while [[ -e "$dest/$basename$num.$ext" ]]; do
            (( num++ ))
      done
      mv "$source" "$dest/$basename$num.$ext" 
fi 

1 Comment

this requires dest to be a directoy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.