LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Move file and change directory in one command (https://www.linuxquestions.org/questions/linux-general-1/move-file-and-change-directory-in-one-command-705634/)

Ztyx 02-18-2009 08:40 AM

Move file and change directory in one command
 
Hi,

I am a UNIX/Linux users since ten years back and I've been using the terminal (BASH) almost daily since then.

One thing that has always annoyed me is the lack of a command to move a file (mv) to a directory and then immediately cd (ie. change directory) to that same destination. This would be a very nifty command saving both my time and wrists!

Example:
Code:

arnold@computer:~/path$ mkdir newpath
arnold@computer:~/path$ touch newfile
arnold@computer:~/path$ mvcd newfile newpath
arnold@computer:~/path/newpath$

Now, from the little I know about BASH programming I could either write a script or use aliasing.

Using a script would not, as I see it, work because changing directory withing the script would only change current directory within the script and not outside in my terminal instance.

Writing an alias I am not sure would be possible unless some parameter magic can be done within the alias functionality.

Is there anyone who has got the slightest idea to take on this silly little quest?

Thanks Jens

pixellany 02-18-2009 08:56 AM

You can:
1. Write a script
2. Use ";"

Ztyx 02-18-2009 09:44 AM

1. A script does not work because the $PWD is local to the script. A child process cannot export variables back to the parent processes that spawned them.
2. Elaborate. I cannot see how using a ';' would yield anything useful in this case as long as it was possible to extract the parameters when using aliasing.

colucix 02-18-2009 10:06 AM

Another possibility is to define a function in your .bashrc. It can be something like this:
Code:

function mvc(){
  num_of_files=$(($# - 1))
  for i in $(eval echo {1..$num_of_files})
  do
    eval mv \$$i \$$#
  done
  eval cd \$$#
}

For example:
Code:

$ pwd
/home/colucix/source
$ ls
file1  file2  file3
$ mvc file* ../dest
$ pwd
$ /home/colucix/dest
$ ls
$ file1  file2  file3
$


Ztyx 02-19-2009 02:40 AM

Thanks! A few simple modifications and this works like a charm:
Code:

function mvcd {
  mv $*
  eval last=\$$#
  cd $last
}

(just put in .bashrc and the mvcd command works next time you start BASH)

Thanks again!

Jens

colucix 02-19-2009 02:49 AM

Very good! Indeed no need to loop over files. Well done! :)

theYinYeti 02-19-2009 03:40 AM

Not so sure. Up to 8 files to move, I think this would work, but beyond that, the 9-parameters limit is reached and the script fails. This should work:
Code:

function mvcd {
  mv "$@"
  while [ $# -gt 1 ]; do shift; done
  cd "$1"
}

Example:
Code:

$ function test() {
> echo number: $#
> eval last=\$$#
> echo last: $last
> }
$ test un deux trois quatre cinq six sept huit neuf dix onze douze
number: 12
last: un2
$ function test() {
> echo number: $#
> while [ $# -gt 1 ]; do shift; done
> echo last: $1
> }
$ test un deux trois quatre cinq six sept huit neuf dix onze douze
number: 12
last: douze

Yves.

Valery Reznic 02-19-2009 04:05 AM

Quote:

Originally Posted by theYinYeti (Post 3449333)
Not so sure. Up to 8 files to move, I think this would work, but beyond that, the 9-parameters limit is reached and the script fails. This should work:
Code:

function mvcd {
  mv "$@"
  while [ $# -gt 1 ]; do shift; done
  cd "$1"
}


While it works, I think 'mv "$@"' may be dangerous one. OK, not more dangerous then 'mv' itself, but still... Some time ago I intended to do following:

Code:

  mv *.c some_dir
But I was too quick, and instead I did
Code:

  mv *.c
Usually mv refuse do it:
Code:

mv: target `XXX' is not a directory
But unfortunately I had only two .c files, so it became
Code:

mv a.c b.c
And of course mv was just happy to overwrite b.c

So as precaution:
Code:

function mvcd {
  if [ $# -ne 2 -o -d $2 ] then
    mv "$@"
    while [ $# -gt 1 ]; do shift; done
    cd "$1"
  else
    echo "Last argument should be directory" 1>&2
    return 1
  fi
}


colucix 02-19-2009 04:09 AM

Yves, you are right! Thanks for notice. However in bash you can avoid the problem using brackets to envelop positional parameters greater than 9. So, following the example I posted above, this version should work
Code:

function mvc ()
{
    num_of_files=$(($# - 1))
    for i in $(eval echo {1..$num_of_files})
    do
        eval mv \${$i} \${$#}
    done
    eval cd \${$#}
}



All times are GMT -5. The time now is 01:03 AM.