Linux mv file with long name

Solution 1:

for a single file try

mv dir1/dir2/dir3/file.{txt,txt.old}

where the X{a,b} construct expand to Xa Xb, you can have a preview using

echo dir1/dir2/dir3/file.{txt,txt.old}

to see if it fit your need.

note:

  1. that for multiple files

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

is unlikely to expand to what you want. (this will expand to a mixed of file.txt file1.txt.old file2.txt ...)

  1. {txt,txt.old} can be shorterned to {,.old} as per comment

  2. if directory name are unambigous, wildcard can be used.

    mv *1/*2/d*/*.{,old}
    

for multiple file use rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

drop -n to have effective rename.

Solution 2:

The command rename renames all matched files. Its main purpose is to rename multiple files, but if the Perl expression matches only one file, then it will rename only this single file. For details and distro specific syntax please read the manpage: man rename.

Example usage: rename "/path/file.txt" to "/path/file.txt.old":

rename 's/file.txt/file.txt.old/g' /path/file.txt

Shorter notation (thanks to shalomb):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

For a dry run use rename -n.

More examples and details can be found at https://thepcspy.com/read/bulk-rename-files-in-ubuntu/


Solution 3:

I like @archemar's solution of using {} expansion, because you can use it when you have already started your command line. Here are some other possibilities for completeness:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(quotes are only necessary if you have spaces or other word-breaking characters in the name)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Notes:

  • This is bash syntax, you might be using another shell
  • mymv can be any reasonable string, I used mymv for "my move".
  • The function definition can be put in your .bash_profile

Another one:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

but

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(from @Adam and @CharlesDuffy) is arguably better in case the cd fails.


Solution 4:

For a one-off case, if I want to not change my current directory I might just use a sub-shell:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Because you cd inside the sub-shell, you haven't changed your directory in your actual shell


Solution 5:

If you want to enter the subdirectory in order to shorten the mv command, but want to come back to the current directory afterwards, there are two ways to do that. One is to put the cd and mv in a subshell (as has already been suggested).

The other is to use pushd and popd to change directories:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

Thepushd command is like cd, except it first pushes the name of the current directory onto a stack. popd removes the top name from the stack and changes to that directory.