I'd like to move multiple files at the same time to specific new locations.

Say I have the following

wrong name  | c.txt | a.txt | b.txt |
Correct name| a.txt | b.txt | c.txt |

I'd then like to doe something like to do something like

mv ./{a.txt,b.txt,c.txt} ./{b.txt,c.txt,a.txt}

but I get the error

  • I don't understand how you are determining the names. You first state c,a,b and a,b,c but then you move a,b,c to b,c,a. Is there any pattern to this or are you just determining these names at random? – jesse_b Nov 29 '18 at 14:34
  • @jesse_b I have some files that were named wrongly (compared to their content) so a currently holds what file b should hold – Thorbjørn E. K. Christensen Nov 29 '18 at 14:40

An addition to @Kusalananda's answer:

You can make it generic with a function:

mv_files() {

  local args=("$@")
  local num_args=${#args[@]}

  if [ $(bc <<< "$num_args%2") -ne 0 ]; then

    echo "Number of arguments must be a multiple of 2."
    return 1


    num_files=$(bc <<< "$num_args/2")
    tmpdir=$(mktemp -d -p .)
    for (( i=0;i<num_files;i++ )); do
      local n=$(bc <<< "$i+$num_files")
      mv "${args[$i]}" "${tmpdir}/${args[$n]}"

    mv ${tmpdir}/* .
    rmdir ${tmpdir}
    echo "Done."


And then you run it like this:

mv_files a.txt b.txt c.txt b.txt c.txt a.txt

or as you did it:

mv_files ./{a.txt,b.txt,c.txt} ./{b.txt,c.txt,a.txt}


old=( a.txt b.txt c.txt )
new=( b.txt c.txt a.txt )

mv_files "${old[@]}" "${new[@]}" 

Notice that

mv ./{a.txt,b.txt,c.txt} ./{b.txt,c.txt,a.txt}

expands to

mv ./a.txt ./b.txt ./c.txt ./b.txt ./c.txt ./a.txt

before the mv utility is called. Since there are more than two operands and since the last operand is not a directory, you get an error. If the last operand was the pathname of a directory, this would have moved all files into that directory (you would also get some errors from specifying some files twice).

Instead, move one file at a time into a temporary directory, renaming them to their correct names while doing so. Then move them back.

mkdir t
mv a.txt t/b.txt
mv b.txt t/c.txt
mv c.txt t/a.txt
mv t/*.txt ./
rmdir t

There is no shortcut for this, the mv utility can only rename one file at a time.

  • is there another way to oneline rename the files like this then? – Thorbjørn E. K. Christensen Nov 29 '18 at 14:38
  • @ThorbjørnE.K.Christensen Other than taking the individual commands and stringing them together with ; in-between each instead of newlines? No, not really. Not if the names can't be computed somehow. – Kusalananda Nov 29 '18 at 14:39
Tried by below method

aveen_linux_example ~]#  sed -n '/wrong name/p' filename | sed "s/|//g" | sed "s/ /\n/g"| sed '/^$/d'|awk '$1 !~  /wrong/ && $1 !~/name/{print $0}' > final.txt
[root@praveen_linux_example ~]# sed -n '/Correct name/p' filename| sed "s/|//g" |sed -r "s/\s+/\n/g"| sed '/^$/d'| awk '$1 !~/Correct/ && $1 !~/name/{print $0}' >final_2.txt

paste final.txt final_2.txt | awk '{print "mv" " " $1 " "  $2}'| sh

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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